Git push & checkout

此篇介绍Git push & checkout的本质。曾经的我认为:push 指令做的事是「上传本地提交」。

Start

先说关键点

push 这个指令的本质:

  1. push 是把当前的分支上传到远程仓库,并把这个 branch 的路径上的所有 commits 也一并上传。
  2. push 的时候,如果当前分支是一个本地创建的分支,需要指定远程仓库名和分支名,用 git push origin branch_name 的格式,而不能只用 git push(只能把本地 master 的最新位置更新到远端,并且把它的路径上的 commits 上传);
  3. push 的时候之后上传当前分支,并不会上传 HEAD;远程仓库的 HEAD 是永远指向默认分支(即 master)的。push 的时候只会上传当前的 branch 的指向,并不会把本地的 HEAD 的指向也一起上传到远程仓库。
1
2
3
4
5
6
7
8
$ git-exercise git:(main) git push
只能在main上简写。
$ git-exercise git:(sami) git push origin sami
~
remote: Create a pull request for 'sami' on GitHub by visiting:
remote: https://github.com/cutegentle/git-exercise/pull/new/sami
To github.com:cutegentle/git-exercise.git
* [new branch] sami -> sami

1

在sami分支使用tig查看提交历史,更能理解branch可以作为从initial开始的一条

checkout 本质

实质上,checkout 并不止可以切换 branchcheckout 本质上的功能其实是:签出( checkout )指定的 commit

git checkout branch名 的本质,其实是把 HEAD 指向指定的 branch,然后签出这个 branch 所对应的 commit 的工作目录。所以同样的,checkout 的目标也可以不是 branch,而直接指定某个 commit

1
2
3
4
git checkout HEAD^^
git checkout master~5
git checkout 78a4bc
git checkout 78a4bc^

存在疑问:

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
$ git-exercise git:(main) git checkout 128b
Note: switching to '128b'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

git switch -c <new-branch-name>

Or undo this operation with:

git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 128b182 Initial commit
恢复:
$ git-exercise git:(128b182) git checkout main
Previous HEAD position was 128b182 Initial commit
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

checkout 和 reset 的不同

checkoutreset 都可以切换 HEAD 的位置,它们除了有许多细节的差异外,最大的区别在于:reset 在移动 HEAD 时会带着它所指向的 branch 一起移动,而 checkout 不会。当你用 checkout 指向其他地方的时候,HEAD 和 它所指向的 branch 就自动脱离了。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!