Git 分支

2019-11-06

Git 分支

几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本(需要把主线上的内容完全复制到分支中)。对于大项目来说,这样的过程会耗费很多时间。

有人把 Git 的分支模型称为它的`‘必杀技特性’’,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。

分支简介

Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。

在进行提交操作时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象

Git 的master 分支并不是一个特殊分支。 它就跟其他分支完全没有区别。 但是几乎每一个仓库都有master分支,是因为git init命令默认创建他,并且大多数人都不会去动他

Git分支的应用场景

公司开发一个网站,为实现某一个功能创建了一个新的分支,这个时候正在这个这个分支上改 代码呢,然后网站突然有个很严重的问题需要你立马解决,你这个时候切换到master主分支上,然后在当前的地方在拉去 一个分支下来,在这个分支上修复错误,当错误修复完成之后再合并到master分支上,然后接着切换到最初的地方的那个分支继续工作。你可能现在不理解这个,看到后面你就会明白。

Git分支正题

Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。Git 会使用 master 作
为分支的默认名字。在若干次提交后,你其实已经有了一个指向最后一次提交对象的
master 分支,它在每次提交的时候都会自动向前移动。
image.png

创建分支

[root@zsf_node3 git_test]# git branch testing

image.png

Git是通过HEAD这个特殊指针来确定他当前在哪个分支上的,在本例中,你仍然在 master 分支上。 因为 git branch 命令仅仅 创建 一个新分支,并不会自动切换到新分支中去。
image.png

查看当前所在的分支

// 星号*所在的位置就是当前处于的分支
[root@zsf_node3 git_test]# git branch 
* master    
  testing
[root@zsf_node3 git_test]# git log --oneline --decorate
9a65100 (HEAD -> master, testing) del one line
6f6a758 add two line
578e3c2 touch test_file

切换当前所处的分支

[root@zsf_node3 git_test]# git checkout testing 
Switched to branch 'testing'
[root@zsf_node3 git_test]# git branch 
  master
* testing

HEAD当前所处的分支
image.png

在分支中提交文件

[root@zsf_node3 git_test]# touch testing_file
[root@zsf_node3 git_test]# git add testing_file
[root@zsf_node3 git_test]# git commit  -m 'touch file on testing' testing_file
[testing 7f7d5b0] touch file on testing
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 testing_file

image.png

把HEAD指针在切换到master上

[root@zsf_node3 git_test]# ls 
test_file  testing_file
[root@zsf_node3 git_test]# git checkout master 
Switched to branch 'master'
[root@zsf_node3 git_test]# ls 
test_file
// 你会发现我们在testing分支上创建的文件在master分支上没有
// 这个时候你因该能体会到了 git 分支的奇特之处了吧

image.png

当我们执行了 git checkout master 之后实际上发生了两件事,git帮我们把HEAD指针指向了master分支,并将工作目录恢复成master分支所指向的快照 内容。
**注意:**在切换分支时,一定要注意你工作目录里的文件会被改变。如果是切换到了一个比较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子,如果git不能 干净利落的完成这个任务,他将禁止切换分支。

我们在次在master分支上修改工作文件

[root@zsf_node3 git_test]# ls 
test_file
[root@zsf_node3 git_test]# echo "branch to master" >> test_file 
[root@zsf_node3 git_test]# git commit -a -m "branch  to master" 
[master 0ce3cc7] branch  to master
 1 file changed, 1 insertion(+)

当我们在master分支上从新进行一次commit的时候,当前git的结构就变成下面这样的了
image.png

刚才我们在testing branch上进行了一次commit,然后我们又切换到master branch进行了一次commit,这两次提交的内容是不一样的,咱们可以在不通分之间不断地来回切换和工作,并在合适的时候我们在将他合并起来。

查看分支操作的历史

[root@zsf_node3 git_test]# git log --oneline --decorate --graph --all
* 0ce3cc7 (HEAD -> master) branch  to master
| * 7f7d5b0 (testing) touch file on testing
|/  
* 9a65100 del one line
* 6f6a758 add two line
* 578e3c2 touch test_file

git创建一个分支实际就相当于往一个文件中写入41个字节(40个字符Commit_id和1个换行符),他的实质上仅仅是包含指向对象校验和(commit_id 长度为40的SHA-1值字符串)

创建并切换分支

[root@zsf_node3 git_test]# git checkout -b paste_test
Switched to a new branch 'paste_test'
[root@zsf_node3 git_test]# git branch 
  master
* paste_test
  testing
  
git checkout -b paste_test这条命令相当于下面两条命令
git branch paste_test && git checkout paste_test 

合并分支

当合并分支的时候你一定要注意是哪个分支合并到哪个分支,打个比方我们想把paste_test分支合并到master分支上,我们需要切换到master分支上来进行合并,合并到哪个分支上就要在哪个分支上操作,合并分支的命令为git merge branch

[root@zsf_node3 git_test]# touch paste_file
[root@zsf_node3 git_test]# git add paste_file
[root@zsf_node3 git_test]# git commit -m "test touch paste_file" paste_file
[paste_test f1ec182] test touch paste_file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 paste_file
[root@zsf_node3 git_test]# ls 
paste_file  test_file
[root@zsf_node3 git_test]# git checkout master 
Switched to branch 'master'
[root@zsf_node3 git_test]# git branch 
* master
  paste_test
  testing
[root@zsf_node3 git_test]# ls 
test_file

[root@zsf_node3 git_test]# git merge paste_test 
Updating 0ce3cc7..f1ec182
Fast-forward
 paste_file | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 paste_file
[root@zsf_node3 git_test]# ls 
paste_file  test_file

聪明的你肯定能看懂我写的这个例子,如果你看不懂你可以在仔细的看看,或者加入笔者的QQ群895291458

聪明的您一定想到如果当前两个需要合并的分支之间的文件有冲突呢?那是以哪个文件里面的为主呢?下面我们 通过实验来解决这个问题

// 当前所处的分支
[root@zsf_node3 git_test]# git branch 
* master
  paste_test
  testing
// 当前master分支里面test_file的文件内容
[root@zsf_node3 git_test]# cat test_file 
add one line
branch to master
// 切换到testing分支
[root@zsf_node3 git_test]# git checkout testing 
Switched to branch 'testing'
[root@zsf_node3 git_test]# ls 
test_file  testing_file
// 修改了test_file文件里面的内容
[root@zsf_node3 git_test]# cat test_file 
This file was changed by the testing branch
// 然后在testing分支commit这个文件
[root@zsf_node3 git_test]# git commit -a -m "changed by the testing branch"
[testing d227a1e] changed by the testing branch
 1 file changed, 1 insertion(+), 1 deletion(-)
 // 切回到master分支
[root@zsf_node3 git_test]# git checkout master 
Switched to branch 'master'
// 然后把testing branch paste master branch
[root@zsf_node3 git_test]# git merge testing 
Auto-merging test_file  //自动合并test_file文件
CONFLICT (content): Merge conflict in test_file  //test_file文件有冲突
Automatic merge failed; fix conflicts and then commit the result.
// 自动合并失败,你需要手工去修复这个错误

从上面这个测试来看,当两个分支进行合并的时候,如果有的文件内容起冲突,他是没办法进行正常合并的,他不会帮我们选择以哪个文件为准,他会把冲突的地方给我们标记出来,然后让我们自己修改,修改完成之后再手工进行commit操作,下面我们现实解决冲突

[root@zsf_node3 git_test]# cat test_file 
<<<<<<< HEAD            
add one line        //当前所在分支里test_file的文件和testing分支中test_file文件起冲突的地方
branch to master
=======
This file was changed by the testing branch
>>>>>>> testing  //testing branch中test_file文件起冲突的地方,我们手工解决他
[root@zsf_node3 git_test]# vim test_file 
[root@zsf_node3 git_test]# git commit -a -m "fix conflicts and then commit the result."
[master 9197e93] fix conflicts and then commit the result.
[root@zsf_node3 git_test]# git status 
On branch master
nothing to commit, working tree clean

删除分支

[root@zsf_node3 git_test]# git branch -d testing 
Deleted branch testing (was d227a1e).
[root@zsf_node3 git_test]# git branch 
* master
  paste_test

查看每个分支的最后一次提交

[root@zsf_node3 git_test]# git branch -v
* master     9197e93 fix conflicts and then commit the result.
  paste_test f1ec182 test touch paste_file

查看已经合并到当前的分支

[root@zsf_node3 git_test]# git branch --merged 
* master
  paste_test

查看还未合并到当前分支的分支

[root@zsf_node3 git_test]# git branch testing
[root@zsf_node3 git_test]# git branch --no-merged 
[root@zsf_node3 git_test]# git checkout testing 
Switched to branch 'testing'
[root@zsf_node3 git_test]# touch test_branch_file
[root@zsf_node3 git_test]# git add test_branch_file
[root@zsf_node3 git_test]# git commit -m "commit to  test_branch_file"
[testing a1b083a] commit to  test_branch_file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test_branch_file
[root@zsf_node3 git_test]# git checkout master 
Switched to branch 'master'
[root@zsf_node3 git_test]# git branch --no-merged 
  testing

没有被合并的文件被删除的时候回提示错误

[root@zsf_node3 git_test]# git branch --no-merged 
  testing
[root@zsf_node3 git_test]# git branch -d testing 
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.
当前 testing branch为被合并,你如果确定要删除他可以使用-D选项

[root@zsf_node3 git_test]# git branch -D testing 
Deleted branch testing (was a1b083a).
[root@zsf_node3 git_test]# git branch 
* master
  paste_test

分支的应用场景:

多分支操作

image.png
image.png

故障处理

image.png


标题:Git 分支
作者:shoufuzhang
地址:https://www.zhangshoufu.com/articles/2019/11/06/1573022162085.html
名言:The master has failed more times than the beginner has tried.
评论
发表评论