Git 基础学习
前几天做 这篇文章 的时候涉及到了 Git,我感觉很有趣,所以就来学习一下
一、Git 介绍
Git 是一个分布式版本控制系统,用于高效地管理代码的版本历史。它能够记录代码的修改、支持多分支开发、确保数据完整性,并允许团队成员协作开发项目。Git 的分布式特性使其在没有网络的情况下仍能执行大部分操作。它广泛用于软件开发中,并且是平台如 GitHub、GitLab 和 Gitee 的核心工具
Git 的特点
- 分布式架构:
- Git 的每个克隆副本都是一个完整的代码库,包含整个历史记录,独立性强。
- 即使没有网络连接,也可以执行几乎所有操作(提交、查看历史等)。
- 高效的性能:
- Git 在处理大文件或复杂的代码库时具有很高的效率。
- 常见操作如分支切换、合并和提交都非常快速。
- 数据完整性:
- Git 使用 SHA-1 哈希值(安全散列算法)来唯一标识每个提交、文件、分支等,确保数据的完整性。
- 非线性开发:
- 支持多分支开发模式,允许开发人员在不同分支上同时进行开发而互不干扰。
- 广泛的生态支持:
- 支持许多工具和平台,如 GitHub、GitLab、Bitbucket 等。
Git 的核心概念
- 版本库 (Repository):
- Git 的工作区域分为两部分:工作目录和版本库。
- 本地版本库存储项目的完整历史。
- 分支 (Branch):
- 分支允许开发者同时开发多个功能,主分支(如
main
或 master
)通常用来存储稳定版本。
- 提交 (Commit):
- 提交是对工作目录的一个快照,每次提交都会生成一个唯一的哈希值。
- 暂存区 (Staging Area):
- 用于存储提交之前的更改,提交时会提交暂存区中的内容。
- 远程仓库 (Remote Repository):
- 用于在团队中共享代码,通过拉取(pull)、推送(push)等操作与远程仓库同步。
二、基础命令
环境配置
所需 |
作用 |
安装了 Git 服务器 |
作为操作,任意系统(这里选择 Ubuntu 24.04.1 LTS x86_64) |
一个 Github 私有仓库(Private Repository) |
作为上传到互联网的仓库(这里创建了一个 https://github.com/AnitsuriW/test 的私有仓库) |
注:本文里,会有像是 那样会有带 的上角标的东西,把鼠标放在那些角标上面,可以看里面的注释的内容
1. 创建私有仓库
其实这里的 Github 仓库可以建 公有(Public) 的,但是这里我们就不给公共互联网上添污了
到 https://github.com/new 下面选择 Private,创建一个私有(Private) 的 Github 仓库,用于上传
- Repository name(仓库名)随便写,这里就写成
test
- Description(描述)可选,这里就不写了
然后点击 Create Repository(创建仓库) 来创建仓库
2. 获取&绑定主机 SSH Key
由于我们设置的是私有仓库,所以我们如果要使用虚拟机访问的话,我们首先要让 Github 知道我们虚拟机的 SSH 密钥
在 Ubuntu 虚拟机上,执行以下操作,获取虚拟机的 SSH 公钥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 创建 SSH 公钥
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
# 按 Enter
Enter file in which to save the key (/home/moka/.ssh/id_rsa):
# 按 Enter
Enter passphrase (empty for no passphrase):
# 按 Enter
Enter same passphrase again:
Your identification has been saved in /home/moka/.ssh/id_rsa
Your public key has been saved in /home/moka/.ssh/id_rsa.pub
The key fingerprint is:
......
# 查看 SSH 公钥
$ cat ~/.ssh/id_rsa.pub
ssh-rsa ......
|
将 cat 到的 ~/.ssh/id_rsa.pub
文件内容复制,然后去到 Github 的 Key 页面 点击 New SSH Key(新建 SSH 密钥)
然后在 Key 栏填入刚才复制的公钥,Title(标题) 任意写,Key Type(密钥类型)就是默认的 Authentication Key(认证密钥)即可
然后点击 Add SSH Key
然后回到虚拟机,测试一下能否连通
1
2
3
4
5
6
7
8
|
$ ssh -T git@github.com
The authenticity of host 'github.com (20.27.177.113)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
# 这里写 yes
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Hi AnitsuriW! You've successfully authenticated, but GitHub does not provide shell access.
|
能看到 Hi AnitsuriW! You've successfully authenticated, but GitHub does not provide shell access.
欢迎字符就说明可以连通,后面 but 的不用管,他只是在提示你 “Github 不提供 shell 访问”(但是 Git 可以 XD
3. 获取 Github 的 个人访问令牌(Personal access tokens)
而要往这个仓库里上传东西的话,我们就需要让 Github 知道“我是谁”,哪个账号是“我”的,而这个就需要用到 个人访问令牌(Personal access tokens) 了
我们进入到 个人访问令牌页面,然后点击 Generate new token,选择合适的权限(通常需要选择 repo
权限),我们这里为了方便后续操作,就全选了
- Token Name(令牌名字)随便写
- Expiration(有效期)我们就按照默认的 30 天即可
- Description(描述)可写可不写,这里就不写了
- Repository access(仓库访问)这里选择 All repositories(所有仓库)
- Permissions(权限)只需要在下面的 Repository permissions(仓库权限)全选 Read and Write 或者是其他那个选项里面最高的权限即可,Account permissions(账号权限)可以不用管,默认即可
然后点击 Generate Token 来创建密钥
然后记住这个密钥,因为他只生成一次
4. 在虚拟机里安装 Git 并配置全局变量
字面意思,回到我们的 Ubuntu 虚拟机,执行以下操作
1
2
3
4
5
6
7
8
|
# 安装 Git
$ sudo apt install -y git
# 配置全局变量
# 配置 Git 提交用户的用户名
$ git config --global user.name "AnitsuriW"
# 配置 Git 提交用户的邮箱
$ git config --global user.email "moka@anitsuri.top"
|
如果你需要“只让第一次输入密码”的话,也可以安装一个 Git Credential Manager (GCM) 用来存储密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 我们这里是 Ubuntu 的,所以下载 .deb 的包
$ wget https://github.com/git-ecosystem/git-credential-manager/releases/download/v2.6.0/gcm-linux_amd64.2.6.0.deb
# 然后来安装一下
$ sudo dpkg -i gcm-linux_amd64.2.6.0.deb
# 如果这个方法不可以,我们可以尝试手动安装
$ dpkg-deb -x gcm-linux_amd64.2.6.0.deb gcm_extracted
$ sudo cp gcm_extracted/usr/local/share/gcm-core/git-credential-manager /usr/local/bin/git-credential-manager-core
# 检验安装是否成功
$ git-credential-manager-core --version
2.6.0+3c28096588f549cb46f36b552390514356830abe
# 然后配置存储密码的全局变量
$ git config --global credential.helper manager-core
|
当下次遇到需要输入密码(比如 git push
)的时候,它就会自动帮你存储密码
那我们 Git 的基础环境配置就到这里了
入门篇
首先是要创建一个用于保存代码的本地目录,这里可以用两种方法:
git clone
git init
+ git remote add
0.1 git clone
git clone
是一个用于从远程仓库复制整个代码库到本地的命令。它会将远程仓库的所有内容(包括代码、分支、提交历史等)完整地下载到你的电脑上,并创建一个与远程仓库关联的本地仓库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# 用 git clone 来克隆我们上面创建的空仓库
$ git clone https://github.com/AnitsuriW/test
正克隆到 'test'...
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
warning: 您似乎克隆了一个空仓库。
|
Username for 'https://github.com':
这里输入 Github 的用户名
Password for 'https://AnitsuriW@github.com'
这里输入之前获取到的 个人访问令牌(Personal access tokens)
然后我们可以看到 GCM 已经帮我们保存了我们的个人访问令牌(Personal access tokens),下次再遇到输入个人访问令牌(Personal access tokens)的时候,GCM 就会帮我们自动填写
我们还可以看到 Git 来了一个警告 warning: 您似乎克隆了一个空仓库。
因为我们的仓库里面还没有任何东西
0.2 git init + git remote add
除了上面的方法,我们还可以通过 创建一个本地的仓库,然后引用到我们的远程仓库 来进行同步数据
git init
是初始化一个新的 Git 仓库的命令。它会在当前目录下创建一个 .git
目录,标志该目录成为一个 Git 仓库
git remote add
是将一个远程仓库与本地仓库关联起来的命令,常用于配置本地仓库与远程仓库的同步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 创建一个新目录,用于初始化成为本地 Git 仓库
# 这里为了做区分,我们就创建一个 test2 目录
$ mkdir test2
$ cd test2
# 然后 git init 初始化这个仓库
$ git init
提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
提示:配置使用初始分支名,并消除这条警告,请执行:
提示:
提示: git config --global init.defaultBranch <名称>
提示:
提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。
提示:可以通过以下命令重命名刚创建的分支:
提示:
提示: git branch -m <name>
已初始化空的 Git 仓库于 /home/moka/test2/.git/
# 添加一下对 AnitsuriW/test 的 Github 仓库的关联
$ git remote add origin https://github.com/AnitsuriW/test.git
# 检验一下
$ git remote -v
origin https://github.com/AnitsuriW/test.git (fetch)
origin https://github.com/AnitsuriW/test.git (push)
|
我们可以看到:这个文件夹的 fetch
的 和 push
的仓库都变成了我们刚刚创建的 test 远程仓库
我们这时候可以使用 git pull
来抓取远程仓库的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
$ git pull origin master
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
fatal: 无法找到远程引用 master
|
- 这里面的
git pull origin master
是要抓取的仓库的 “远程” 和 “分支”
- 一般来说,这里的 “远程” 都是 origin,“分支” 是 master 或者是 main
- 我们可以看到我们刚才配置的 GCM 没有起作用,这是不是坏了?
- 不是的,是因为我们这是一个新的文件夹了,Git 就会默认以为不是一个东西了
- 我们还可以看到这里有提示
fatal: 无法找到远程引用 master
,因为我们目前还是一个空仓库
※ 下面的命令,为了方便,都是使用 git clone
创建的文件夹 test
来操作
1. git add
git add
是 Git 中用于将 工作区(Working Directory) 中的更改(新增、修改、删除的文件)添加到 暂存区(Staging Area) 的命令
git add
告诉 Git,“我已经准备好提交这些更改了”。只有被添加到暂存区的更改,才会在后续的 git commit
中被提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 新建一个 README.md 文件,并且写上一些内容
$ touch README.md
$ echo "这是一个 Git 学习用的测试仓库" >> README.md
# 添加到暂存区
$ git add README.md
# 检验一下
# 查看暂存区的命令: git diff --cached
$ git diff --cached
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9e1d12b
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+这是一个 Git 学习用的测试仓库
|
- 我们可以看到,
README.md
正常添加到暂存区了,而且还显示了修改的内容
2. git commit
简单来说,git commit
就像在你的代码本子上盖了一个章,记录下「此时此刻代码的状态和变化」。每次盖章后,Git 会帮你记住这次修改的内容、修改的原因(通过提交信息),以及谁盖的章和什么时候盖的。
它的作用就是给代码做“快照”,方便你以后翻看和恢复某一刻的代码状态。比如,今天你盖了一章说明「修复了登录问题」,明天又盖了一章说明「新增了注册功能」。如果某天出了问题,你可以轻松回到「修复登录问题」时的状态
常用选项
-m "<提交信息>"
:提交代码时直接附带提交信息,避免进入编辑器
-a
:自动将所有已修改的文件添加到暂存区,然后提交(不包括新建的文件)
--amend
:修改上一次的提交信息或内容,通常用来修复错误提交
--no-edit
:使用上一次提交的信息,不打开编辑器(常与 --amend
配合使用)
--verbose
:提交时显示具体的修改内容,便于确认提交的更改
--dry-run
:模拟提交,显示会发生什么,但不会真的提交
--allow-empty
:提交一个空的 commit,不包含任何更改,通常用于标记特殊状态或事件
--squash
:将更改合并到上一次的提交中(通常在变基时使用)
--reset-author
:重置提交的作者信息,常用于调整提交归属
虽然介绍了这么多,但是我们这次只用 -m "<提交信息>"
这一个选项
我们可以把刚才添加到暂存区的文件给 commit 一下
1
2
3
4
5
6
7
8
9
10
11
12
|
$ git commit -m "add README.md"
[main (根提交) eef23fe] add README.md
1 file changed, 1 insertion(+)
create mode 100644 README.md
# 校验一下
$ git log
commit eef23fe250729d4b3dc89d66f86c5beeb095e6b7 (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:43:53 2024 +0800
add README.md
|
我们可以看到,在 main 下面有一个 哈希(Hash)值 开头为 eef23fe
的 commit 被创建了
以及用 git log
可以看到我们刚刚创建的 Git,以及创建的人是 AnitsuriW,邮箱是 moka@anitsuri.top
,也就是我们上面配置的全局变量
3. git branch
git branch
是一个用于管理分支的 Git 命令
它可以创建、删除、重命名分支,或者是列出所有分支,或查看当前所在的分支
常用选项
git branch (什么都不加)
:列出所有的分支
git branch <分支名>
:创建一个新的分支
-d
:删除本地分支(分支必须已被合并)
-D
:强制删除本地分支(即使未合并)
-m
:重命名分支
-r
:列出所有远程分支
-a
:列出所有本地分支和远程分支
我们可以创建一个 test 的 branch(分支)
1
2
3
4
5
6
|
$ git branch test
# 检验一下
$ git branch
* main
test
|
我们可以看到,确实创建了一个本地分支 test,但是我们目前还在 main 分支下
4. git checkout
git checkout
是一个用于切换分支或恢复文件的 Git 命令
它可以切换到指定的分支或提交,或者是恢复工作区中的文件到特定版本
我们可以使用它来切换到我们刚刚创建的 test 分支,但是在此之前,我们先了解一下它有哪些常用的选项
常用选项
git checkout <分支名>
:切换到指定分支
-b <新分支名>
:创建并切换到新分支 ( = git branch <新分支名>
+ git checkout <新分支名>
)
git checkout <文件名>
:恢复工作区的文件到暂存区版本
git checkout <提交ID> -- <文件名>
:恢复文件到指定提交的版本
git checkout <提交ID>
:将工作区切换到指定提交(分离头指针状态)
git checkout -- <文件名>
:丢弃文件在工作区的更改,取消文件更改(实验分支回退)
好,介绍完了常用选项之后,回到我们刚刚问题:切换到 test 分支
1
2
3
4
5
6
7
|
$ git checkout test
切换到分支 'test'
# 检查一下
$ git branch
main
* test
|
5.1 git merge
git merge
是 Git 中用于将一个分支的更改合并到当前分支的命令。通常在团队协作中,当不同开发者在不同分支上工作时,git merge
用于将一个分支的工作合并到另一个分支,以便完成集成
使用 git merge
在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个 parent 节点。翻译成自然语言相当于:“我要把这两个 parent 节点本身及它们所有的祖先都包含进来。”
常用选项
--no-ff <分支名>
:创建一个新的合并提交,即使可以快进合并,也不进行快进,保持合并记录
--squash <分支名>
:将目标分支的更改压缩成一个提交,合并到当前分支,不保留分支历史
--abort
:取消合并并恢复到合并前的状态
为了方便理解,我们先在 test 分支下创建一个 commit
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ touch README.md
$ echo "这是 test 分支的README" >> README.md
$ git add README.md
$ git commit -m "add test-branch README.md"
[test d91b17a] add test-branch README.md
1 file changed, 1 insertion(+)
$ touch README_test.md
$ echo "这是 test 分支的README" >> README_test.md
$ git add README_test.md
$ git commit -m "add README_test.md"
[test 168eaeb] add README_test.md
1 file changed, 1 insertion(+)
create mode 100644 README_test.md
|
然后这时候我们切换回 main 分支,并创建一个 commit
1
2
3
4
5
6
7
8
9
10
11
12
|
$ git checkout main
切换到分支 'main'
您的分支基于 'origin/main',但此上游分支已经不存在。
(使用 "git branch --unset-upstream" 来修复)
$ touch README_main.md
$ echo "这是 main 分支的README" >> README_main.md
$ git add README_main.md
$ git commit -m "add README_main.md"
[main 16d5d4a] add README_main.md
1 file changed, 1 insertion(+)
create mode 100644 README_main.md
|
然后我们使用 git merge
合并 main 分支 和 test 分支,到新的 main 分支下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$ $ git merge test
Merge made by the 'ort' strategy.
README.md | 1 +
README_test.md | 1 +
2 files changed, 2 insertions(+)
create mode 100644 README_test.md
# 检验一下
$ git branch
* main
test
$ ls -al
总计 24
drwxrwxr-x 3 moka moka 4096 12月 21 11:49 ./
drwxr-x--- 18 moka moka 4096 12月 21 11:49 ../
drwxrwxr-x 8 moka moka 4096 12月 21 11:49 .git/
-rw-rw-r-- 1 moka moka 28 12月 21 11:47 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
$ cat README.md
这是一个 Git 学习用的测试仓库
这是 test 分支的README
|
我们可以看到,在合并完成之后,test 分支的内容被合并到 main 分支下,并且合并了两个分支下的 README.md
,形成了一个 “新” 的 main 分支
此时我们回到 test 分支,并且查看 README.md
文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$ git checkout test
切换到分支 'test'
$ git branch
main
* test
$ ls -l
总计 20
drwxrwxr-x 3 moka moka 4096 12月 21 11:50 ./
drwxr-x--- 18 moka moka 4096 12月 21 11:50 ../
drwxrwxr-x 8 moka moka 4096 12月 21 11:50 .git/
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
$ cat README.md
这是一个 Git 学习用的测试仓库
这是 test 分支的README
|
会发现 test 分支下的 README.md
文件也发生了变化,但是多出来的 README_main.md
并没有在这里面,说明 test 分支并没有合并到 main 分支下
此时,我们可以选择再使用一次 git merge
命令,来让 test 分支的内容合并到和 main 分支一样(但依旧是两个分支)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$ git merge main
更新 168eaeb..b9d059b
Fast-forward
README_main.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README_main.md
$ ls -l
总计 24
drwxrwxr-x 3 moka moka 4096 12月 21 11:53 ./
drwxr-x--- 18 moka moka 4096 12月 21 11:50 ../
drwxrwxr-x 8 moka moka 4096 12月 21 11:53 .git/
-rw-rw-r-- 1 moka moka 28 12月 21 11:53 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
|
再次合并之后可以看到,test 分支里面的文件也和 main 分支一样了
5.2 git rebase
上面介绍的 git merge
是一种合并分支的方法,而现在介绍的 git rebase
则是第二种合并分支的方法,Rebase 实际上就是取出一系列的提交记录,“复制” 它们,然后在另外一个地方逐个的放下去
Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰
常用选项
git rebase <目标分支>
:将当前分支的提交应用到 <目标分支>
的最新状态上
-i <目标分支>
:会打开一个编辑器(默认是 nano
)启动交互式 rebase,允许你对提交进行修改、合并、删除或重排序
--onto <新基底分支> <起始分支> <当前分支>
:将两个分支,合并成一个新基底的分支
--continue
:在解决冲突后继续进行 rebase 操作
--skip
:跳过当前提交(在冲突解决不必要时)
--abort
:取消当前的 rebase 操作,并恢复到 rebase 前的状态
--rebase-merges
:保留合并提交,同时支持交互式 rebase(也可以用 --preserve-merges
,但是那个更古老,没这个好)
--autosquash
:自动压缩提交,将以 fixup!
或 squash!
开头的提交与其对应的基础提交合并
为了方便理解,我们还是在目前分支(test 分支)和 main 分支下各创建一个 git commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# 在当前(test)分支下
$ touch test.md
$ echo "testtesttest123123" >> test.md
$ git add test.md
$ git commit -m "add test.md"
[test e795bee] add test.md
1 file changed, 1 insertion(+)
create mode 100644 test.md
$ git checkout main
切换到分支 'main'
您的分支基于 'origin/main',但此上游分支已经不存在。
(使用 "git branch --unset-upstream" 来修复)
# 在 main 分支下
$ touch main.md
$ echo "main is main, master is master" >> main.md
$ git add main.md
$ git commit -m "add main.md"
[main e95695c] add main.md
1 file changed, 1 insertion(+)
create mode 100644 main.md
|
然后我们回到 test 分支,并执行 git rebase
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$ git checkout test
切换到分支 'test'
$ git rebase main
成功变基并更新 refs/heads/test。
$ ls -l
总计 32
drwxrwxr-x 3 moka moka 4096 12月 21 15:23 ./
drwxr-x--- 18 moka moka 4096 12月 21 15:05 ../
drwxrwxr-x 8 moka moka 4096 12月 21 15:23 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 15:23 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:53 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
-rw-rw-r-- 1 moka moka 19 12月 21 15:23 test.md
|
可以看到有我们刚刚在 test 分支上的 test.md
,也有在 main 分支上创建的 main.md
,也合并过来了
但是这里面的 test 分支已经变基了,换种说法说就是在 main 分支下,创建一个 “和 test 分支修改内容相同的” commit,然后将 test 分支移过来
然而此时,我们切换到 main 分支看的话
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ git checkout main
切换到分支 'main'
您的分支基于 'origin/main',但此上游分支已经不存在。
(使用 "git branch --unset-upstream" 来修复)
$ ls -l
总计 28
drwxrwxr-x 3 moka moka 4096 12月 21 15:29 ./
drwxr-x--- 18 moka moka 4096 12月 21 15:05 ../
drwxrwxr-x 8 moka moka 4096 12月 21 15:29 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 15:23 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:53 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
|
我们会发现,main 分支并没有我们刚刚创建的 test 分支上的东西
此时,我们也可以选择再次使用 git rebase
来给 main 分支合并一下 test 分支里面的东西
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
$ git merge test
更新 e95695c..5a10341
Fast-forward
test.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test.md
$ ls -l
总计 32
drwxrwxr-x 3 moka moka 4096 12月 21 17:15 ./
drwxr-x--- 18 moka moka 4096 12月 21 15:05 ../
drwxrwxr-x 8 moka moka 4096 12月 21 17:15 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 15:23 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:53 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 11:49 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 11:49 README_test.md
-rw-rw-r-- 1 moka moka 19 12月 21 17:15 test.md
|
因为 test 分支是从 main 分支合并的,所以 main 分支要是合并到 test 分支的话,直接 “落” 下来就行
6. 分离 HEAD
首先,我们先了解一下 HEAD。HEAD 是一个对当前所在分支的符号引用 — 也就是指向你正在其基础上进行工作的 commit
HEAD 通常是指向当前分支最近的 commit,大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的
HEAD 通常情况下是指向分支名的(比如 test)。在你提交时,改变了 test 的状态,这一变化通过 HEAD 变得可见
我们可以看一下,我们刚刚给 main 进行了合并的 git log
1
2
3
4
5
6
7
|
# 查看最近一次 git log
$ git log -1
commit 5a1034134430d820a97c0e1bc4e44cb5a7ca3751 (HEAD -> main, test)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:19:42 2024 +0800
add test.md
|
可以看到,当前 HEAD 在 哈希值为 5a1034134430d820a97c0e1bc4e44cb5a7ca3751
的 commit 下,当前 commit 里面是 main 分支 和 test 分支 的 最新 commit
这里面的 HEAD 指向 main 和 test,main 和 test 指向 5a1034134430d820a97c0e1bc4e44cb5a7ca3751
的 commit
7.1 相对引用 ^
通过指定 commit 的 哈希值 来在 Git 上面移动不太方便,还得一个一个看 git log
,虽然能直接输入前四位的哈希值来跳,但是也比较麻烦
就没有一个比较方便的方法吗?欸🤓👆,你看小标题:相对引用 ^ 来辣
这玩意特别厉害,这个相对引用,可以以某个分支为基准,也可以以 HEAD 为基准
- 使用
^
向上移动 1 个提交记录
- 使用
~<num>
向上移动多个提交记录,如 ~3
我们可以通过 git log -1
看现在的 HEAD 在哪
1
2
3
4
5
6
|
$ git log -1
commit 5a1034134430d820a97c0e1bc4e44cb5a7ca3751 (HEAD -> main, test)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:19:42 2024 +0800
add test.md
|
我们现在在 add test.md
的 commit 下,然后我们使用 git checkout
或者是 git switch
来切换一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
$ git checkout HEAD^1
注意:正在切换到 'HEAD^1'。
您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以在切换回一个分支时,丢弃在此状态下所做的提交而不对分支造成影响。
如果您想要通过创建分支来保留在此状态下所做的提交,您可以通过在 switch 命令中添加参数 -c 来实现(现在或稍后)。例如:
git switch -c <新分支名>
或者撤销此操作:
git switch -
通过将配置变量 advice.detachedHead 设置为 false 来关闭此建议
HEAD 目前位于 e95695c add main.md
# 检验一下
$ git log -1
commit e95695cb4f19edc9fdbce4b4ace29f23c7e26758 (HEAD)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:21:48 2024 +0800
add main.md
|
可以看到切换的时候也有在提示 「您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以在切换回一个分支时,丢弃在此状态下所做的提交而不对分支造成影响」和 「HEAD 目前位于 e95695c add main.md」
我们使用 git log -1
校验的时候也能看到在 add main.md
下
7.2 相对引用 ~
如果想要在 Git 里面移动很多步的话,打好几个 ^
也挺麻烦的,Git 也觉得麻烦,所以他们搞出了 ~
这个操作
~
后面可以接一个数字(比如 ~3
),指定向上移动多少次,也可以什么都不接(和 ^
一样)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
$ git log
commit e95695cb4f19edc9fdbce4b4ace29f23c7e26758 (HEAD)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:21:48 2024 +0800
add main.md
commit b9d059bdfe3dd69fe1eb3853214105afa4b5046d
Merge: 16d5d4a 168eaeb
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:49:15 2024 +0800
Merge branch 'test'
commit 16d5d4a2be036d54cf4006378b34f5c0b35a8e60
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:48:33 2024 +0800
add README_main.md
commit 168eaeb21feb70f2dda35914eaf45089e82c3d51
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:46:21 2024 +0800
add README_test.md
commit d91b17aa7bbaa2c4cd529bb44ebf576ac9d12223
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:44:52 2024 +0800
add test-branch README.md
commit eef23fe250729d4b3dc89d66f86c5beeb095e6b7
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:43:53 2024 +0800
add README.md
$ git checkout HEAD~3
之前的 HEAD 位置是 e95695c add main.md
HEAD 目前位于 eef23fe add README.md
|
我们可以看到,这里面的 HEAD 指针,由原来的「e95695c add main.md」到了现在的「eef23fe add README.md」,来到了最开始创建 README.md 的位置上,此时查看我们的 README.md
1
2
|
$ cat README.md
这是一个 Git 学习用的测试仓库
|
可以看到,我们回到了刚才学习 git add
和 git commit
的 “刚刚 add main 分区的 README.md” 位置上
8.1 git reset
git reset
是用于撤销更改的命令,可以将提交、暂存区或工作区的状态回滚到之前的状态。它改变的是提交历史或暂存区的状态,不会保留撤销记录,“改写历史”
常用选项
git reset <文件名>
:移出暂存区的文件
--soft <提交ID>
:将分支指针回退到指定提交,但保留修改内容在暂存区
--mixed <提交ID>
:回退提交并清空暂存区
--hard <提交ID>
:分支指针、暂存区和工作区都恢复到指定提交的状态,所有未提交的更改会丢失
为了方便理解,我们这里先将 HEAD 切换到 main 分支里面最新的 commit
1
2
3
4
5
|
$ git checkout main
之前的 HEAD 位置是 eef23fe add README.md
切换到分支 'main'
您的分支基于 'origin/main',但此上游分支已经不存在。
(使用 "git branch --unset-upstream" 来修复)
|
然后我们退回到上一个 commit(刚添加完 main.md
并没有合并 test 分支)
1
2
3
4
5
6
7
8
9
|
$ git reset HEAD~1
# 检验一下
$ git log -1
commit e95695cb4f19edc9fdbce4b4ace29f23c7e26758 (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:21:48 2024 +0800
add main.md
|
我们可以看到,正常回到上一个 commit 了,而我们最新的 git log
也是没有了合并 test 分支的那一个 log,是真正的 “改写了历史”,但是此时改写还没结束……
8.2 git revert
git revert
是用于撤销某次提交的命令,通过生成一个新的提交来反转指定提交的更改。它不会修改提交历史,而是安全地在项目中记录撤销操作
常用选项
git revert <提交ID>
:撤销指定的提交,创建一个新的提交来反转指定的提交
git revert <提交ID1> <提交ID2> ...
:连续撤销多个提交
--no-edit <提交ID>
:自动提交撤销结果,跳过编辑提交消息的步骤,直接使用默认消息
--no-commit <提交ID>
:在不提交的情况下生成撤销更改,仅生成撤销的更改,保留在暂存区,你可以手动调整后提交
-m <父提交编号> <合并提交ID>
:用于撤销合并提交,-m
后的数字表示选择哪一方作为基线(通常为 1
)
我们刚才修改了 main 分支,现在让我们切换到 test 分支
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
$ git checkout test
error: 工作区中下列未跟踪的文件将会因为检出操作而被覆盖:
test.md
请在切换分支前移动或删除。
正在终止
$ git branch
* main
test
$ ls -l
总计 32
drwxrwxr-x 3 moka moka 4096 12月 21 20:56 ./
drwxr-x--- 18 moka moka 4096 12月 21 21:10 ../
drwxrwxr-x 8 moka moka 4096 12月 21 21:06 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 20:56 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 20:56 README_main.md
-rw-rw-r-- 1 moka moka 70 12月 21 20:56 README.md
-rw-rw-r-- 1 moka moka 28 12月 21 20:56 README_test.md
-rw-rw-r-- 1 moka moka 19 12月 21 20:56 test.md
|
我们会发现 Git 不让我们切换到 test 分支,因为我们刚刚 git reset
的 “修改历史” 行为还没结束,main 分支里还有一个 “没处理” 的 test.md
文件
我们可以将这个文件使用 git add
+ git commit
新建一个 commit,或者是 git rebase
来和刚才一样,合并两个分支
此时,为了方便,我们可以使用刚刚没用过的 git add
+ git commit
来修改
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ git add test.md
$ git commit -m "add test.md in main branch"
[main 247f2ab] add test.md in main branch
1 file changed, 1 insertion(+)
create mode 100644 test.md
# 检验一下
$ git log -1
commit 247f2aba9e6cc831ceab3097e7a00331a213cad3 (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 21:15:18 2024 +0800
add test.md in main branch
|
我们能看到,即使修改的文件是一样的,但是 commit 不一样,所以两个分支还是不同
那我们添加完成之后就可以撤销刚刚对 main 分支进行的修改了
我们直接撤销前面的第二个操作(也就是 合并 README_main.md
和 README_test.md
的操作)
1
2
3
|
$ git revert HEAD~2
error: 提交 b9d059bdfe3dd69fe1eb3853214105afa4b5046d 是一个合并提交但未提供 -m 选项。
fatal: 还原失败
|
什么?提交失败?原因是因为我们没有指定 b9d059bdfe3dd69fe1eb3853214105afa4b5046d
(合并 test 分支的) 的 commit 是基于哪个分支进行做的
此时,提示我们使用 -m
选项来选择父提交,如果你不确定是哪个父提交的话,可以用 git log -1 --pretty=format:%P HEAD~2
来确认一下往上的两个操作的合并提交是哪个父提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
$ git log -1 --pretty=format:%P HEAD~2
16d5d4a2be036d54cf4006378b34f5c0b35a8e60 168eaeb21feb70f2dda35914eaf45089e82c3d51
$ git log
commit 247f2aba9e6cc831ceab3097e7a00331a213cad3 (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 21:15:18 2024 +0800
add test.md in main branch
commit e95695cb4f19edc9fdbce4b4ace29f23c7e26758
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:21:48 2024 +0800
add main.md
commit b9d059bdfe3dd69fe1eb3853214105afa4b5046d
Merge: 16d5d4a 168eaeb
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:49:15 2024 +0800
Merge branch 'test'
commit 16d5d4a2be036d54cf4006378b34f5c0b35a8e60
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:48:33 2024 +0800
add README_main.md
commit 168eaeb21feb70f2dda35914eaf45089e82c3d51
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:46:21 2024 +0800
add README_test.md
commit d91b17aa7bbaa2c4cd529bb44ebf576ac9d12223
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:44:52 2024 +0800
add test-branch README.md
|
我们可以很清楚的看到
-m 1
是对应的哈希值是 16d5d4a2be036d54cf4006378b34f5c0b35a8e60
的提交,也就是 “add README_main.md” 的提交
-m 2
是对应的哈希值是 168eaeb21feb70f2dda35914eaf45089e82c3d51
的提交,也就是 “add README_test.md” 的提交
根据我们的需要(在 main 分支上保留原本 main 分支的内容),我们回到最晚创建的那个,也就是 -m 1
的分支
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
$ git revert -m 1 HEAD~2
[main 29974b2] Revert "Merge branch 'test'"
2 files changed, 2 deletions(-)
delete mode 100644 README_test.md
$ ls -l
总计 28
drwxrwxr-x 3 moka moka 4096 12月 21 21:45 ./
drwxr-x--- 18 moka moka 4096 12月 21 21:40 ../
drwxrwxr-x 8 moka moka 4096 12月 21 21:45 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 20:56 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 20:56 README_main.md
-rw-rw-r-- 1 moka moka 42 12月 21 21:45 README.md
-rw-rw-r-- 1 moka moka 19 12月 21 20:56 test.md
$ git log
commit 29974b22d8d8206e6cfdd1fe88f70639976566ec (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 21:45:43 2024 +0800
Revert "Merge branch 'test'"
This reverts commit b9d059bdfe3dd69fe1eb3853214105afa4b5046d, reversing
changes made to 16d5d4a2be036d54cf4006378b34f5c0b35a8e60.
commit 247f2aba9e6cc831ceab3097e7a00331a213cad3
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 21:15:18 2024 +0800
add test.md in main branch
commit e95695cb4f19edc9fdbce4b4ace29f23c7e26758
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 15:21:48 2024 +0800
add main.md
commit b9d059bdfe3dd69fe1eb3853214105afa4b5046d
Merge: 16d5d4a 168eaeb
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:49:15 2024 +0800
Merge branch 'test'
commit 16d5d4a2be036d54cf4006378b34f5c0b35a8e60
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:48:33 2024 +0800
add README_main.md
commit 168eaeb21feb70f2dda35914eaf45089e82c3d51
Author: AnitsuriW <moka@anitsuri.top>
Date: Sat Dec 21 11:46:21 2024 +0800
add README_test.md
|
我们可以看到,他在 commit 中通过复制一份的方式,保留了通过 git rebase
合并的 test.md
和 main.md
,但是删除了一开始通过 git merge
合并的 README_test.md
9. git cherry-pick
git cherry-pick
是 Git 中一个强大的命令,用于从一个分支的提交历史中 挑选指定的 commit 并将其应用到当前分支
它是代码合并中非常有用的工具,适用于将某些特定的更改引入到另一个分支,而不是整个分支的合并
简单来说就是能将别的分支的 某个/某些 commit 直接合并到当前 HEAD 的下面,而不用合并分支
常用选项
-e
:在应用 commit 前允许编辑提交信息
--no-commit
/ -n
:将更改应用到工作区但不自动提交 commit,适合进一步修改后再提交
-x
:在 commit 信息中添加一行,标记该提交是由 cherry-pick
生成的,并注明原始 commit 哈希值
--continue
:在冲突解决后继续 cherry-pick
操作
--abort
:取消当前的 cherry-pick
操作并恢复到原始状态
--quit
:退出当前 cherry-pick
操作,但保留未解决的冲突
--strategy=<strategy>
:指定合并策略(如 recursive
、resolve
等)
--allow-empty
:允许挑选空 commit
--skip
:跳过当前冲突的 commit 并继续执行后续的 cherry-pick
我们可以在 main 上 添加/修改 几个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# 修改
$ echo "这是一个测试 的文本,我来试试好不好用" >> README.md
$ echo "这是一个测试 git cherry-pick 的文本,我来试试好不好用" >> README.md
$ git commit -m "change README.md file"
[main 9c38a3d] change README.md file
1 file changed, 2 insertions(+)
# 添加文件
$ touch cherry-pick.txt
$ echo "测试测试测试测试" > cherry-pick.txt
$ git add cherry-pick.txt
$ git commit -m "add cherry-pick.txt"
[main b432e76] add cherry-pick.txt
1 file changed, 1 insertion(+)
create mode 100644 cherry-pick.txt
# 查看 Hash 值
$ git log -2
commit b432e765af7c887cf78e8f8fd325b0f0bea6a2eb (HEAD -> main)
Author: AnitsuriW <moka@anitsuri.top>
Date: Sun Dec 22 10:18:49 2024 +0800
add cherry-pick.txt
commit 9c38a3d1685fe3ebf00d8f7162c2bf9b6d63f827
Author: AnitsuriW <moka@anitsuri.top>
Date: Sun Dec 22 10:17:51 2024 +0800
change README.md file
|
可以看到,这两个 commit 的哈希值分别是 9c38a3d1685fe3ebf00d8f7162c2bf9b6d63f827
和 b432e765af7c887cf78e8f8fd325b0f0bea6a2eb
,我们这里只需要取前五个字符就行,即 9c38a
和 b432e
然后 git cherry-pick
到 test 分支里
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 先把 HEAD 移过去
$ git checkout test
切换到分支 'test'
# 然后再 cherry-pick
$ git cherry-pick 9c38a b432e
自动合并 README.md
冲突(内容):合并冲突于 README.md
error: 不能应用 9c38a3d... change README.md file
提示:解决所有冲突之后,用 "git add/rm <路径规格>" 标记它们,
提示:然后执行 "git cherry-pick --continue"。您也可以执行
提示:"git cherry-pick --skip" 命令跳过这个提交。如果想要终止执行并回到
提示:执行 "git cherry-pick" 之前的状态,执行 "git cherry-pick --abort"。
|
可以看到对于修改的 README.md 的内容,git cherry-pick
给出的回答是 “冲突”
此时我们需要查看这个文件,并处理这个冲突,比如我们这次想要两个都保留
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# 查看 README.md
$ cat README.md
这是一个 Git 学习用的测试仓库
<<<<<<< HEAD
这是 test 分支的README
=======
这是一个测试 的文本,我来试试好不好用
这是一个测试 git cherry-pick 的文本,我来试试好不好用
>>>>>>> 9c38a3d (change README.md file)
# 然后我们编辑这个文件,呈下面的这个样子
$ vi README.md
这是一个 Git 学习用的测试仓库
这是 test 分支的README
这是一个测试 的文本,我来试试好不好用
这是一个测试 git cherry-pick 的文本,我来试试好不好用
# 将文件存为暂存区 = 冲突解决
$ git add README.md
# 告诉 git cherry-pick 冲突已解决
$ git cherry-pick --continue
[test 21edeb3] change README.md file
Date: Sun Dec 22 10:17:51 2024 +0800
1 file changed, 2 insertions(+)
[test f975980] add cherry-pick.txt
Date: Sun Dec 22 10:18:49 2024 +0800
1 file changed, 1 insertion(+)
create mode 100644 cherry-pick.txt
# 检验
$ ls -l
总计 36
drwxrwxr-x 3 moka moka 4096 12月 22 16:02 ./
drwxr-x--- 18 moka moka 4096 12月 22 16:00 ../
-rw-rw-r-- 1 moka moka 25 12月 22 16:02 cherry-pick.txt
drwxrwxr-x 8 moka moka 4096 12月 22 16:02 .git/
-rw-rw-r-- 1 moka moka 31 12月 21 20:56 main.md
-rw-rw-r-- 1 moka moka 28 12月 21 20:56 README_main.md
-rw-rw-r-- 1 moka moka 199 12月 22 16:00 README.md
-rw-rw-r-- 1 moka moka 28 12月 22 10:21 README_test.md
-rw-rw-r-- 1 moka moka 19 12月 21 20:56 test.md
$ cat cherry-pick.txt
测试测试测试测试
$ cat README.md
这是一个 Git 学习用的测试仓库
这是 test 分支的README
这是一个测试 的文本,我来试试好不好用
这是一个测试 git cherry-pick 的文本,我来试试好不好用
|
可以看到解决完冲突之后,运行 git cherry-pick --continue
就会继续进行 git cherry-pick
操作,且和我们刚刚想要的,两处修改的内容都有保留
远程篇
远程仓库并不复杂,在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西,但实际上它们只是你的仓库在另个一台计算机上的 copy。你可以通过 Internet 与你的计算机通信 — 也就是增加或是获取提交记录
话虽如此, 远程仓库却有一系列强大的特性
- 首先也是最重要的的点,远程仓库是一个强大的备份
本地仓库也有恢复文件到指定版本的能力, 但所有的信息都是保存在本地的
有了远程仓库以后,即使丢失了本地所有数据, 你仍可以通过远程仓库拿回你丢失的数据
- 还有就是, 远程让代码社交化了!
既然你的项目被托管到别的地方了, 你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)
现在用网站来对远程仓库进行可视化操作变得越发流行了(像 GitHub), 但远程仓库永远是这些工具的顶梁柱, 因此理解其概念非常的重要!
由于远程篇的 git add
和 git remote
上面已经讲了,但并没有细说,或者说并没有和 “远程篇” 的放到一起,所以这里等会再单独说一下
10. git push
git push
从字面意思可以看出来,它是往远程仓库 “push” 的
git push
负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。一旦 git push
完成, 你的朋友们就可以从这个远程仓库下载你分享的成果了!
你可以将 git push
想象成发布你成果的命令,并且他有很多的技巧
注意 — git push
不带任何参数时的行为与 Git 的一个名为 push.default
的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是 upstream
。 这没什么太大的影响,但是在你的项目中进行推送之前,最好检查一下这个配置。
常用选项
git push <remote> <branch>
:指定远程仓库和分支
-u
:设置本地分支和远程分支的关联关系(仅首次推送需要)
--all
:推送所有本地分支到远程仓库
--tags
:推送所有的本地标签到远程仓库
-f
:强制推送,覆盖远程的提交历史(谨慎使用)
--force-with-lease
:比 --force
更安全,仅在远程分支没有变化时强制推送,防止覆盖他人提交
--delete <branch_name>/tag <tag_name>
:删除远程分支或标签
--dry-run
:模拟推送,显示将要推送的内容,但不实际执行操作
--mirror
:完全镜像推送,包括所有分支、标签以及远程配置。适用于同步整个仓库
-q
:隐藏推送时的输出信息,适用于减少控制台输出的场景
--no-verify
:跳过推送前的钩子验证(如 pre-push)
--recurse-submodules=check
:在推送前检查子模块的状态,并提示未推送的更改
我们可以将我们上面 “基础篇” 学习到的内容都同步到我们 Github 的仓库里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# 先上传 main
$ git branch
main
* test
$ git checkout main
切换到分支 'main'
您的分支基于 'origin/main',但此上游分支已经不存在。
(使用 "git branch --unset-upstream" 来修复)
$ git push origin main
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
枚举对象中: 28, 完成.
对象计数中: 100% (28/28), 完成.
使用 4 个线程进行压缩
压缩对象中: 100% (20/20), 完成.
写入对象中: 100% (28/28), 2.62 KiB | 537.00 KiB/s, 完成.
总共 28(差异 6),复用 0(差异 0),包复用 0
remote: Resolving deltas: 100% (6/6), done.
To https://github.com/AnitsuriW/test
* [new branch] main -> main
# 然后再上传 test 分支的
moka@moka-Ubutu01:~/test$ git checkout test
切换到分支 'test'
moka@moka-Ubutu01:~/test$ git push origin test
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
枚举对象中: 11, 完成.
对象计数中: 100% (11/11), 完成.
使用 4 个线程进行压缩
压缩对象中: 100% (7/7), 完成.
写入对象中: 100% (9/9), 980 字节 | 980.00 KiB/s, 完成.
总共 9(差异 2),复用 0(差异 0),包复用 0
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
remote:
remote: Create a pull request for 'test' on GitHub by visiting:
remote: https://github.com/AnitsuriW/test/pull/new/test
remote:
To https://github.com/AnitsuriW/test
* [new branch] test -> test
|
此时,我们可以在我们的仓库页面 https://github.com/AnitsuriW/test
就能看到我们刚刚 push 上去的两个分支了
11. git clone
git clone
是用于从远程版本控制系统中复制一个完整的仓库到本地的命令。它不仅下载仓库的文件,还包括所有的版本历史记录和分支信息,因此本地仓库是远程仓库的完整副本
由于我们刚才在 0.1 的时候就已经使用过 git clone
了,那咱们现在来深入地看一下发生了什么。
你可能注意到的第一个事就是在我们的本地仓库多了一个名为 origin/main
的分支, 这种类型的分支就叫 远程 分支。由于远程分支的特性导致其拥有一些特殊属性。
远程分支反映了远程仓库(在你上次和它通信时)的状态。这会有助于你理解本地的工作与公共工作的差别 — 这是你与别人分享工作成果前至关重要的一步.
远程分支有一个特别的属性,在你切换到远程分支时,自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果
你可能想问这些远程分支的前面的 origin/
是什么意思呢?好吧, 远程分支有一个命名规范 —— 它们的格式是:
<remote name>/<branch name>
因此,如果你看到一个名为 origin/main
的分支,那么这个分支就叫 main
,远程仓库的名称就是 origin
大多数的开发人员会将它们主要的远程仓库命名为 origin
,这是因为当你用 git clone
某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin
了
剩下的这里就不再多讲了,只是为大家介绍一下 git clone
常见的一些选项
常用选项
--depth <N>
:浅克隆,只获取最近的 N
次提交
-b <分支名>
:克隆特定分支,而非默认分支
--single-branch
:只克隆指定分支,不包含其他分支信息
--mirror
:完全克隆,包括所有分支和远程配置信息,适用于创建镜像备份
这里换了一台新设备来简单演示一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
$ git clone https://github.com/AnitsuriW/test
正克隆到 'test'...
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
remote: Enumerating objects: 37, done.
remote: Counting objects: 100% (37/37), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 37 (delta 13), reused 29 (delta 7), pack-reused 0 (from 0)
接收对象中: 100% (37/37), 4.71 KiB | 689.00 KiB/s, 完成.
处理 delta 中: 100% (13/13), 完成.
|
然后我们也可以尝试切换到刚才提到过的远程分支试一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
$ cd test
$ git checkout origin/main
注意:正在切换到 'origin/main'。
您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以在切换
回一个分支时,丢弃在此状态下所做的提交而不对分支造成影响。
如果您想要通过创建分支来保留在此状态下所做的提交,您可以通过在 switch 命令
中添加参数 -c 来实现(现在或稍后)。例如:
git switch -c <新分支名>
或者撤销此操作:
git switch -
通过将配置变量 advice.detachedHead 设置为 false 来关闭此建议
HEAD 目前位于 e61c0f6 Merge pull request #1 from AnitsuriW/test
|
可以看到切换到远程分支了,且 HEAD 头分离
我们这个时候可以提交一个 commit 来试一下
1
2
3
4
5
6
|
$ touch test3.txt
$ git add test3.txt
$ git commit -m "add test3.txt"
[分离头指针 026a1e5] add test3.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test3.txt
|
然后切换回本地的 main 分支
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$ git checkout main
警告:您正丢下 1 个提交,未和任何分支关联:
026a1e5 add test3.txt
如果您想要通过创建新分支保存它,这可能是一个好时候。
如下操作:
git branch <新分支名> 026a1e5
切换到分支 'main'
您的分支与上游分支 'origin/main' 一致。
$ ls -l
总计 32
drwxrwxr-x 3 moka moka 4096 12月 24 13:36 ./
drwxr-x--- 18 moka moka 4096 12月 24 13:36 ../
-rw-rw-r-- 1 moka moka 25 12月 24 13:29 cherry-pick.txt
drwxrwxr-x 8 moka moka 4096 12月 24 13:36 .git/
-rw-rw-r-- 1 moka moka 31 12月 24 13:29 main.md
-rw-rw-r-- 1 moka moka 28 12月 24 13:29 README_main.md
-rw-rw-r-- 1 moka moka 199 12月 24 13:29 README.md
-rw-rw-r-- 1 moka moka 19 12月 24 13:29 test.md
|
可以看到,即使我们在 origin/main
分支中提交 commit 了,但是文件还是没有保存
这是因为 origin/main
只有在远程仓库中相应的分支更新了以后才会更新,在 origin/main 上做的所有 commit 最后都会消失
12. git fetch
git fetch
是一个从远程仓库获取更新的命令,用于将远程仓库中的变更(如新提交、分支、标签等)下载到本地,而不自动合并到当前分支。
这是一个“安全”的操作,因为它不会更改工作目录或本地分支的内容,仅更新本地的远程跟踪分支
如果你还记得我们刚刚说过的,远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch
就是你与远程仓库通信的方式了!
git fetch
通常通过互联网(使用 http://
或 git://
协议) 与远程仓库通信
-
git fetch 不会做的事
git fetch
并不会改变你本地仓库的状态。它不会更新你的 main
分支,也不会修改你磁盘上的文件
理解这一点很重要,因为许多开发人员误以为执行了 git fetch
以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。我们在后面的课程中将会讲解能完成该操作的命令 :D
所以, 你可以将 git fetch
的理解为单纯的下载操作
常用选项
git fetch
:获取远程仓库的所有更新
<remote> <refspec>
:指定从哪个远程仓库拉取更新、指定获取的分支或标签范围,可精确控制哪些分支或提交被拉取。如果省略,默认使用 origin main
--all
:从所有远程仓库中获取更新
--prune
:删除本地已失效的远程跟踪分支(远程仓库中已删除的分支)
--dry-run
:模拟获取更新的过程,不实际下载,只显示会被更新的内容
--depth <number>
:限制下载的提交深度,只获取最近的 <number>
次提交,适用于大型仓库或浅克隆
--no-tags
:不从远程仓库中获取标签信息
--tags
:仅从远程仓库获取标签信息,而不获取分支
--recurse-submodules[=<path>]
:在获取主仓库的同时,递归获取子模块的更新。如果指定 <path>
,则只更新特定子模块
我们可以看一下我们现在的分支
可以看到只有 main 分支
此时,我们可以通过 git fetch
来将刚刚 git clone
没有下下来的 test 分支下载下来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
$ git fetch origin test
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
来自 https://github.com/AnitsuriW/test
* branch test -> FETCH_HEAD
|
我们可以使用 git log -1
看一下,test 分支下没下下来
1
2
3
4
5
6
7
8
9
|
$ git log -1
commit e61c0f6b0a833ccdc551112befe86fa3d00dfb45 (HEAD -> main, origin/main, origin/HEAD)
Merge: b432e76 bc64c08
Author: Wang Jiayu <47847633+AnitsuriW@users.noreply.github.com>
Date: Sun Dec 22 16:55:27 2024 +0800
Merge pull request #1 from AnitsuriW/test
add "Test" PR
|
可以看到,我们 HEAD 目前指的是 main 分支,还有没显示的远程分支:origin/main 和 origin/HEAD 分支
但是我们现在的 test 分支,因为还是远程分支状态的 origin/HEAD 分支,所以我们现在需要给他定义一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 在本地创建 test 分支,并让它追踪远程的 test 分支
$ $ git checkout -b test origin/test
分支 'test' 设置为跟踪 'origin/test'。
切换到一个新分支 'test'
# 检验一下
$ git branch
main
* test
$ git log -1
commit bc64c081b9e78d9cb6c13dfd58a9897ceed374fa (HEAD -> test, origin/test)
Merge: f975980 b432e76
Author: Wang Jiayu <47847633+AnitsuriW@users.noreply.github.com>
Date: Sun Dec 22 16:54:49 2024 +0800
Merge branch 'main' into test
|
可以看到现在 HEAD 在 test 分支 和 远程分支 origin/test 分支 上
13. git pull
既然我们已经知道了如何用 git fetch
获取远程的数据,现在我们学习如何将这些变化更新到我们的工作当中。
其实有很多方法的 — 当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支
也就是说就是你可以执行以下命令:
git cherry-pick o/main
git rebase o/main
git merge o/main
- 等等
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要说的 git pull
常用选项
git pull [选项] [远程名] [分支名]
:如果省略远程名和分支名,Git 会尝试使用当前分支的默认远程和分支
--rebase
:将远程分支的更改 重放 到本地分支的提交之上,而不是创建一个新的合并提交
--ff-only
:仅允许快进合并,如果不能快进合并(例如需要创建合并提交),则会报错并中止操作
--no-ff
:强制创建一个合并提交,即使可以快进合并
-q
:禁止输出非错误信息
-v
:显示详细的操作过程信息
--all
:从所有远程仓库获取更新
--no-rebase
:禁用 git pull
时的重演操作(如果配置了默认的 pull.rebase
为 true
时,使用此选项可强制回到合并模式)
--no-commit
:在合并更改后,不会立即创建合并提交,而是将更改暂存在工作区,允许手动编辑和检查
--strategy=<strategy>
:指定合并策略
常用的策略包括:
recursive
: 默认策略,适合两分支有共同祖先的情况。
ours
: 忽略远程分支的更改,保留本地分支内容。
theirs
: 使用远程分支的更改,覆盖本地内容
我们可以在我们的仓库里面,在我们的 test 分支上添加一个 test4.txt 文件
然后我们在机器上使用 git fetch
和 git merge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
$ git fetch
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
展开对象中: 100% (6/6), 1.85 KiB | 40.00 KiB/s, 完成.
来自 https://github.com/AnitsuriW/test
bc64c08..70c83fd test -> origin/test
|
这里可以看到,本地仓库是什么都没有的,是因为 git fetch
的内容是下载到远程的 origin/test 分支里,不会下到本地的 test 分支里
1
2
3
4
5
6
7
8
9
10
|
$ ls -l
总计 32
drwxrwxr-x 3 moka moka 4096 12月 24 14:57 ./
drwxr-x--- 18 moka moka 4096 12月 24 20:05 ../
-rw-rw-r-- 1 moka moka 25 12月 24 14:57 cherry-pick.txt
drwxrwxr-x 8 moka moka 4096 12月 24 15:02 .git/
-rw-rw-r-- 1 moka moka 31 12月 24 14:57 main.md
-rw-rw-r-- 1 moka moka 28 12月 24 14:57 README_main.md
-rw-rw-r-- 1 moka moka 199 12月 24 14:57 README.md
-rw-rw-r-- 1 moka moka 19 12月 24 14:57 test.md
|
所以这里我们就需要 git merge
来合并一下仓库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
$ git merge
更新 bc64c08..108f00a
Fast-forward
text4.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 text4.txt
# 检验一下
$ ls -l
总计 36
drwxrwxr-x 3 moka moka 4096 12月 24 20:12 ./
drwxr-x--- 18 moka moka 4096 12月 24 20:05 ../
-rw-rw-r-- 1 moka moka 25 12月 24 14:57 cherry-pick.txt
drwxrwxr-x 8 moka moka 4096 12月 24 20:12 .git/
-rw-rw-r-- 1 moka moka 31 12月 24 14:57 main.md
-rw-rw-r-- 1 moka moka 28 12月 24 14:57 README_main.md
-rw-rw-r-- 1 moka moka 199 12月 24 14:57 README.md
-rw-rw-r-- 1 moka moka 19 12月 24 14:57 test.md
-rw-rw-r-- 1 moka moka 63 12月 24 20:12 text4.txt
|
可以看到,git fetch
+ git merge
就可以同步远程仓库了
但是,我们这里再介绍一个比较丝滑优雅的方法,那也就是我们现在学的这个 git pull
同理,我们可以在远程仓库里,再写一个 test5.txt 的文件上去
然后,我们使用 git pull
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
$ git pull
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
Username for 'https://github.com': AnitsuriW
Password for 'https://AnitsuriW@github.com':
fatal: No credential store has been selected.
Set the GCM_CREDENTIAL_STORE environment variable or the credential.credentialStore Git configuration setting to one of the following options:
secretservice : freedesktop.org Secret Service (requires graphical interface)
gpg : GNU `pass` compatible credential storage (requires GPG and `pass`)
cache : Git's in-memory credential cache
plaintext : store credentials in plain-text files (UNSECURE)
See https://aka.ms/gcm/credstores for more information.
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
展开对象中: 100% (3/3), 969 字节 | 969.00 KiB/s, 完成.
来自 https://github.com/AnitsuriW/test
108f00a..0ebb0a4 test -> origin/test
更新 108f00a..0ebb0a4
Fast-forward
text5.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 text5.txt
# 查看一下
$ ls -l
总计 40
drwxrwxr-x 3 moka moka 4096 12月 24 20:16 ./
drwxr-x--- 18 moka moka 4096 12月 24 20:05 ../
-rw-rw-r-- 1 moka moka 25 12月 24 14:57 cherry-pick.txt
drwxrwxr-x 8 moka moka 4096 12月 24 20:16 .git/
-rw-rw-r-- 1 moka moka 31 12月 24 14:57 main.md
-rw-rw-r-- 1 moka moka 28 12月 24 14:57 README_main.md
-rw-rw-r-- 1 moka moka 199 12月 24 14:57 README.md
-rw-rw-r-- 1 moka moka 19 12月 24 14:57 test.md
-rw-rw-r-- 1 moka moka 63 12月 24 20:12 text4.txt
-rw-rw-r-- 1 moka moka 63 12月 24 20:16 text5.txt
|
我们可以看到,立马就有 text5.txt 文件了
好了,本期 Git 基础学习文档就到这里结束了,感谢各位的观看!
Specal Thanks: Learn Git Branching