git 什么是分支 branch

一、分支的概念

在这里插入图片描述

Branches are named pointers to commits:分支是指向commits的有名指针。

像上图所示,master指向具体的一个 commit:a219fd,所以 master 是一个分支;dev 指向具体的一个 commit:e78125,所以 dev 也是一个分支。

当前我们有两个问题需要解决:

  • 分支指向的commit 保存在什么地方(即如何知道 master 分支指向的commit值)?
  • 在多个分支的情况下,我们怎么知道当前所处的分支是哪一个?

二、HEAD指针

在这里插入图片描述
我们可以看到,如上图所说:

  • HEAD是一个特殊的指针,HEAD指针指向当前工作的分支;
  • HEAD指针总是指向当前工作的分支的最近(最新)一次 commit;

如上图,当前HEAD指针指向了master分支,所以当前的工作分支是 master分支;同时 master 分支指向的 commit 是 a219fd,也就是上面说的:HEAD指针总是指向工作分支的最近一次 commit。

如果需要切换分支,如切换到 dev 分支。我们可以把 HEAD指针指向 dev 分支,那么 dev 分支就是当前的工作分支了。同时 HEAD指向指向工作分支的最近一次 commit e78125。


三、命令实操

首先,我们使用命令 git log 可以看到当前git版本库中的提交日志,可以看到最近的一次提交是 5269b2e.

root@backvm-virtual-machine:workspace# git log --oneline -3
5269b2e 3rd commit
a4df186 2nd commit
f59d0f4 1st commit
root@backvm-virtual-machine:workspace# 

下面我们可以查看 .git/HEAD 文件,这个文件指向了另外的一个文件 .git/refs/heads/master ,它的内容是 5269b2eea42525594f02c06ef39cff4b56ae3c75,前面部分的内容正好是最近的一次提交:5269b2e .

接着通过命令 git branch --list -v查看分支情况,*master 5269b2e 表示 master 是当前的工作分支,而且分支 commit 是 5269b2e .

root@backvm-virtual-machine:workspace# cat .git/HEAD 
ref: refs/heads/master
root@backvm-virtual-machine:workspace# cat .git/refs/heads/master 
5269b2eea42525594f02c06ef39cff4b56ae3c75
root@backvm-virtual-machine:workspace# 
root@backvm-virtual-machine:workspace# git branch --list  -v
* master 5269b2e 3rd commit
root@backvm-virtual-machine:workspace# 

通过命令 git cat-file -t 5269b2e 可以看到 5269b2e 确实是一个 commit.由此证明 HEAD指针指向的确实是一个 commit。

root@backvm-virtual-machine:workspace# git cat-file -t 5269b2e
commit
root@backvm-virtual-machine:workspace# 

四、其他命令及演示

在这里插入图片描述

可以看到,我们当前的工作分支是 master. 接着通过命令创建 dev 分支: git branch dev. 创建完成之后通过命令 git branch --list可以看到当前的分支有两个: master 和 dev.

root@backvm-virtual-machine:workspace# git branch --list 
* master
root@backvm-virtual-machine:workspace# git branch dev
root@backvm-virtual-machine:workspace# git branch --list 
  dev
* master
root@backvm-virtual-machine:workspace# 

注意创建分支的时候,新创建分支指向的 commit 与当前工作分支的 commit 是相同的.

通过命令 git branch -v 可以看到,当前存在两个分支: master 和 dev,而且这两个分支指向的 commit 都是 5269b2e . 而且 HEAD 指针指向的分支的 commit 也是 5269b2e .

root@backvm-virtual-machine:workspace# git branch -v             
  dev    5269b2e 3rd commit
* master 5269b2e 3rd commit
root@backvm-virtual-machine:workspace# cat .git/HEAD             
ref: refs/heads/master
root@backvm-virtual-machine:workspace# cat .git/refs/heads/master
5269b2eea42525594f02c06ef39cff4b56ae3c75
root@backvm-virtual-machine:workspace# 

可以看到,目录 .git/refs/heads/ 下出现了两个文件:dev 和 master,这两个文件保存的内容正是它们指向的 commit.

root@backvm-virtual-machine:workspace# cat .git/refs/heads/
dev     master  
root@backvm-virtual-machine:workspace# cat .git/refs/heads/dev 
5269b2eea42525594f02c06ef39cff4b56ae3c75
root@backvm-virtual-machine:workspace# cat .git/refs/heads/master
5269b2eea42525594f02c06ef39cff4b56ae3c75
root@backvm-virtual-machine:workspace# 

下面我们开始切换分支. git checkout(change the current active branch), 可以得知, git checkout 可以改变当前工作分支,由于HEAD指针总是指向当前工作分支,所以 git checkout 命令主要是改变 HEAD 指针的指向。

之前 .git/HEAD 指向 refs/heads/master,当前工作分支是 master 分支; 使用命令 git checkout dev之后,.git/HEAD 指向 refs/heads/dev,当前工作分支是 dev分支.

root@backvm-virtual-machine:workspace# cat .git/HEAD 
ref: refs/heads/master
root@backvm-virtual-machine:workspace# 
root@backvm-virtual-machine:workspace# git branch -v
  dev    5269b2e 3rd commit
* master 5269b2e 3rd commit
root@backvm-virtual-machine:workspace# git checkout dev
切换到分支 'dev'
root@backvm-virtual-machine:workspace# cat .git/HEAD   
ref: refs/heads/dev
root@backvm-virtual-machine:workspace# git branch -v   
* dev    5269b2e 3rd commit
  master 5269b2e 3rd commit
root@backvm-virtual-machine:workspace# 

接下来我们在 dev 分支下提交一个 commit.

root@backvm-virtual-machine:workspace# echo "dev" > dev.txt
root@backvm-virtual-machine:workspace# ls
dev.txt  file1.txt  file2.txt  folder1
root@backvm-virtual-machine:workspace# git add dev.txt 
root@backvm-virtual-machine:workspace# git commit -m "1st commit from dev branch"
[dev 27d6ef4] 1st commit from dev branch
 1 file changed, 1 insertion(+)
 create mode 100644 dev.txt

可以看到,当前工作分支 HEAD 指针指向了 dev 分支,而且 dev 分支相比 master 分支前进了一步.

在这里插入图片描述

执行 git checkout 命令切换到 master. 可以看到当前 HEAD 指针指向了 master 分支,而且在 master 分支中 看不到在 master 分支前边 的 dev 分支.
在这里插入图片描述

删除分支有两个参数选项: -d -D. -d 会进行询问,而 -D 将会强制删除分支.

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git branch -d dev
error: The branch 'dev' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev'.

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git branch -D dev
Deleted branch dev (was 27d6ef4).

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)

注意:删除了 dev 分支,但是 dev 分支所创建的 obj 对象还存在,如下图:

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git cat-file -t 27d6ef4  # 查看 27d6ef4, 是一个 commit
commit

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git cat-file -p 27d6ef4  # 查看 27d6ef4 内容
tree 1e7585d019956406d085bbb2fcfbd148b28ff279
parent 5269b2eea42525594f02c06ef39cff4b56ae3c75
author demo <demo@demo.com> 1666368908 +0800
committer demo <demo@demo.com> 1666368908 +0800

1st commit from dev branch

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git cat-file -p 1e7585d  # 查看 tree  对象 1e7585d ,找到了 dev.txt 文件
100644 blob 38f8e886e1a6d733aa9bfa7282568f83c133ecd6    dev.txt
100644 blob 99bdb979298700648a2f7d9a360e98fa1224b7c0    file1.txt
100644 blob 0c9c9cbe89b55ec9867ed28878bb0b73abe04268    file2.txt
040000 tree e3cfebfb440e2af91732e71deda277030d7182e9    folder1

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git cat-file -p 38f8e8  # 查看 blob 对象 38f8e8,可以得到文件的内容
dev

五、再谈 git checkout 命令

git checkout 命令进行 master 分支与 dev 分支切换,本质上只是改变了 HEAD 指针的指向,而 master 分支和 dev 分支指向的各自的commit 并没有发生变化。

同时, git checkout 命令不止可以进行分支切换,还可以 checkout 某一个具体的 commit。

如下图,当前 HEAD 指针指向了 master 分支, master 分支指向了 897fb0 commit.

在这里插入图片描述

可以使用 git checkout 命令将 HEAD 指针指向另外的 commit: 2e4624, 而 master 分支仍然指向了 897fb0 commit.
在这里插入图片描述

下面我们使用 git checkout 命令将 HEAD 指针指向第一次提交 commit.

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git log
commit 5269b2eea42525594f02c06ef39cff4b56ae3c75 (HEAD -> master)
Author: demo <demo@demo.com>
Date:   Fri Oct 21 22:32:42 2022 +0800

    3rd commit

commit a4df1862e6fda55c694c6029022f8acb1c37dcc2
Author: demo <demo@demo.com>
Date:   Fri Oct 21 22:06:31 2022 +0800

    2nd commit

commit f59d0f44413b1857309d793559650a856c26dcbe
Author: demo <demo@demo.com>
Date:   Fri Oct 21 02:19:30 2022 +0800

    1st commit

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git checkout f59d0f
Note: switching to 'f59d0f'.

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 f59d0f4 1st commit

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace ((f59d0f4...))
$ git log
commit f59d0f44413b1857309d793559650a856c26dcbe (HEAD)
Author: demo <demo@demo.com>
Date:   Fri Oct 21 02:19:30 2022 +0800

    1st commit

我们在 checkout 到一个具体的 commit 之后,可以通过新建一个分支(新分支指向的 commit 即是当前 HEAD 指向的 commit),然后再让 HEAD 指向新建的分支,之后就可以在新建的分支上做修改和提交了。

在这里插入图片描述

将分支切换到 master 分支后,tmp分支仍然指向第一次提交的 commit.

在这里插入图片描述
注意:一个分支指向了一个具体的 commit,使用命令 git branch 命令删除了分支,其实只是删除了分支的名字,具体的 commit 并没有被删除。

可以使用 git reflog 查看 HEAD 指针的变化。

可以看到 dev 分支所做的提交的 commit。

在这里插入图片描述

如下,我们可以通过具体的 commit 找到被误删的 commit 记录,从而恢复那个 commit 的内容(即之前被我们误删的 dev 分支)。

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (master)
$ git checkout 27d6ef4
Note: switching to '27d6ef4'.

You are in 'detached HEAD' state. You can look around, make experimental
......
HEAD is now at 27d6ef4 1st commit from dev branch

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace ((27d6ef4...))
$ ls
dev.txt  file1.txt  file2.txt  folder1/

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace ((27d6ef4...))
$ git checkout -b dev
Switched to a new branch 'dev'

zzzzzz@Minami MINGW32 /d/myCode/linux_win_shared/git_demo/workspace (dev)
$ cat dev.txt
dev

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值