GIT分支管理

GIT分支简介:


  Git 把我们之前每次提交的版本串成一条时间线,这条时间线就是一个分支。截止到目前只有一条时间线,在git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。

(1) 一开始的时候,master分支是一条线,git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
GIT分支管理_第1张图片

  • 每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

(2) 当我们创建新的分支,例如dev时,git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
GIT分支管理_第2张图片

  • git创建一个分支很快,因为除了增加一个dev指针,改变HEAD的指向,工作区的文件都没有任何变化。

(3) 不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
GIT分支管理_第3张图片
(4) 假如我们在dev上的工作完成了,就可以把dev合并到master上。git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
GIT分支管理_第4张图片

  • git合并分支也很快,就改改指针,工作区内容也不变。

(5) 合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
GIT分支管理_第5张图片

GIT分支实例:


**(1) 执行如下命令可以查看当前有几个分支并且看到在哪个分支下工作。**
ubantu@ubantu-virtual-machine:~/git_folder$ git branch
* master
ubantu@ubantu-virtual-machine:~/git_folder$ 

(2) 下面创建一个分支dev并切换到其上进行工作。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b dev
Switched to a new branch 'dev'
  • git branch:查看分支(当前所在分支前面会有一个星号
  • git checkout 分支名:切换分支
  • git branch -b 分支名:创建分支
  • git branch -d 分支名:删除分支
    GIT分支管理_第6张图片
    (3) 下面我们修改first.txt内容,在里面添加一行,并进行提交。
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt 
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
ubantu@ubantu-virtual-machine:~/git_folder$ git add first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "dev branch submit"
[dev 3f6bc28] dev branch submit
 1 file changed, 1 insertion(+)

GIT分支管理_第7张图片
(4) dev分支的工作完成,我们就可以切换回master分支:

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master 
Switched to branch 'master'
ubantu@ubantu-virtual-machine:~/git_folder$ git branch 
  dev
 * master

GIT分支管理_第8张图片

  • 查看first.txt,发现添加的内容没有了。因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
ubantu@ubantu-virtual-machine:~/git_folder$ 

(5) 现在,我们把dev分支的工作成果合并到master分支上:

ubantu@ubantu-virtual-machine:~/git_folder$ git merge dev
Updating d7df419..3f6bc28
Fast-forward
 first.txt | 1 +
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$ 
  • git merge命令用于合并指定分支到当前分支。合并后,再查看first.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
ubantu@ubantu-virtual-machine:~/git_folder$ 

GIT分支管理_第9张图片

  • 注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

(6) 合并完成后,就可以放心地删除dev分支了,删除后,查看branch,就只剩下master分支了

ubantu@ubantu-virtual-machine:~/git_folder$ git branch -d dev
Deleted branch dev (was 3f6bc28).
ubantu@ubantu-virtual-machine:~/git_folder$ git branch
* master
ubantu@ubantu-virtual-machine:~/git_folder$ 

GIT分支管理_第10张图片

解决冲突


合并冲突说明:

某个分支修改了一个文件,在未合并到主分支之前,这个文件也被其他分支修改,此时系统不知道以哪个分支修改后的内容为准来合并到主分支,因此在合并分支时就会产生冲突。


(1) 再创建一个新分支dev。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b dev
Switched to a new branch 'dev'
ubantu@ubantu-virtual-machine:~/git_folder$ 

(2) 修改first.txt内容,并进行提交。

ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data
ubantu@ubantu-virtual-machine:~/git_folder$ git add first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "dev branch second submit"
[dev d9e0e8c] dev branch second submit
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$ 

(3) 切换回master分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master
Switched to branch 'master'
ubantu@ubantu-virtual-machine:~/git_folder$ 

(4) 在master主分支的first.txt添加一行内容并进行提交。

ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txtthis is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data in master
ubantu@ubantu-virtual-machine:~/git_folder$ git add first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "master branch submit"
[master c19bc13] master branch submit
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$
  • 现在,master分支和dev分支各自都分别有新的提交,变成了这样:
    GIT分支管理_第11张图片
  • 这种情况下,git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。

(5) 执行如下命令尝试将dev分支合并到master分支上来。

ubantu@ubantu-virtual-machine:~/git_folder$ git merge dev
Auto-merging first.txt
CONFLICT (content): Merge conflict in first.txt
Automatic merge failed; fix conflicts and then commit the result.
ubantu@ubantu-virtual-machine:~/git_folder$
  • 提示我们自动合并产生冲突,冲突文件为first.txt,需要手动修正冲突后再提交

(6) git status也可以告诉我们冲突的文件:

ubantu@ubantu-virtual-machine:~/git_folder$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add ..." to mark resolution)

	both modified:   first.txt

no changes added to commit (use "git add" and/or "git commit -a")
ubantu@ubantu-virtual-machine:~/git_folder$ 
  • 提示我们有尚未合并的路径,需要解决冲突后运行git commit命令
  • 有两个人修改了first.txt文件

(7) 查看code.txt的内容。

ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt 
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
<<<<<<< HEAD
add another data in master
=======
add another data
>>>>>>> dev
ubantu@ubantu-virtual-machine:~/git_folder$

(8) git用以下标记出不同分支的内容(我们手动删除以下内容即可)

<<<<<<<=======>>>>>>>

(9) 我们修改如下后保存

ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data in master
add another data
ubantu@ubantu-virtual-machine:~/git_folder$ 

(9) 再提交。

ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "solve merge conflict" 
[master 194ad75] solve merge conflict
ubantu@ubantu-virtual-machine:~/git_folder$ 

(10) 现在,master分支和dev分支变成了下图所示:
GIT分支管理_第12张图片
(11) 用带参数的git log也可以看到分支的合并情况:

ubantu@ubantu-virtual-machine:~/git_folder$ git log --graph --pretty=oneline
*   194ad7508eb5656a243bf93ca36f6c23412566e1 solve merge conflict
|\  
| * d9e0e8cc0026d256043938ef38ecfe9a1e11bbc0 dev branch second submit
* | c19bc130daf086d984aa1a7395a95a2a580d1998 master branch submit
|/  
* 3f6bc28880f2edd636e5b0527e18f8225bef4209 dev branch submit
* d7df4195d600a5c9d414519c757e91dae50df39c 删除文件second.txt
* f696849773147218c4d72dfb62932be47a079bbc 版本4
* 724a2201044ae9f6fc5f2905fd3b032001a71d51 版本3
* ca3a776239c5532e728ffae0be467584a12215b0 版本2
* 22355f7dffd474ed51ac033e825c67b4393eaa87 版本1
ubantu@ubantu-virtual-machine:~/git_folder$ 

(12) 最后工作完成,可以删除dev分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git branch -d dev
Deleted branch dev (was d9e0e8c).
ubantu@ubantu-virtual-machine:~/git_folder$ git branch
* master
ubantu@ubantu-virtual-machine:~/git_folder$ 

分支管理策略


通常,合并分支时,如果可能,git会用fast forward模式,但是有些时候快速合并不能成功而且没有冲突,这个时候git会帮你合并,并做一次新的提交。但这种模式下,删除分支后,会丢掉分支信息。(在分支上新建并修改某个文件内容之后,还未合并到主分支之前,此时主分支修改了其他文件,然后合并就会出现此种情况)

(1) 创建切换到dev分支下。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b dev
Switched to a new branch 'dev'
ubantu@ubantu-virtual-machine:~/git_folder$

(2) 新建一个文件first2.txt编辑内容如下,并提交一个commit。

ubantu@ubantu-virtual-machine:~/git_folder$ vim first2.txt
ubantu@ubantu-virtual-machine:~/git_folder$ cat first2.txt 
first data commit
ubantu@ubantu-virtual-machine:~/git_folder$ git add first2.txt 
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "create first2.txt file"
[dev 1f40b6f] create first2.txt file
 1 file changed, 1 insertion(+)
 create mode 100644 first2.txt
ubantu@ubantu-virtual-machine:~/git_folder$ 

(3) 切换回master分支,编辑first.txt并进行一个提交。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master 
Switched to branch 'master'
ubantu@ubantu-virtual-machine:~/git_folder$ echo "add another data second" >> first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data in master
add another data
add another data second
ubantu@ubantu-virtual-machine:~/git_folder$ git add first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "add new data"
[master 510d39d] add new data
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$ 

(4) 合并dev分支的内容到master分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git merge dev

(5) 出现如下提时,这是因为这次不能进行快速合并,所以git提示输入合并说明信息,输入之后合并内容之后git会自动创建一次新的提交。

  1 Merge branch 'dev'
  2 
  3 # Please enter a commit message to explain why this merge is necessary,
  4 # especially if it merges an updated upstream into a topic branch.
  5 #
  6 # Lines starting with '#' will be ignored, and an empty message aborts
  7 # the commit.                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~       
  • 我们需要修改第一行,写上我们提交的内容
  1 合并dev分支
  2 
  3 # Please enter a commit message to explain why this merge is necessary,
  4 # especially if it merges an updated upstream into a topic branch.
  5 #
  6 # Lines starting with '#' will be ignored, and an empty message aborts
  7 # the commit.                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~       
ubantu@ubantu-virtual-machine:~/git_folder$
Merge made by the 'recursive' strategy.
 first2.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 first2.txt
ubantu@ubantu-virtual-machine:~/git_folder$ 
  • 保存退出 : wq(注意:如果此处不是vim编辑器则使用ctrl+x然后输入y退出)

(6) 查看日志

ubantu@ubantu-virtual-machine:~/git_folder$ git log --pretty=oneline
4189c3f26784405d7285c49a02e0be13123bb1c1 合并dev分支
62d02bb7aafae14bc625190c00e26aab544e1b93 add new data
  • 我们可以看到此时在添加新数据之后进行了一次合并(这次合并就是git帮我们做的)

(7) 删除dev分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git branch -d dev
Deleted branch dev (was 7c13d45).
ubantu@ubantu-virtual-machine:~/git_folder$ 

如果要强制禁用fast forward模式,git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。


(1) 创建并切换到dev分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b dev
Switched to a new branch 'dev'
ubantu@ubantu-virtual-machine:~/git_folder$ 

(2) 修改first.txt内容,并提交一个commit。

ubantu@ubantu-virtual-machine:~/git_folder$ echo "add another data third" >> first.txt 
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt 
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data in master
add another data
add another data second
add another data third
ubantu@ubantu-virtual-machine:~/git_folder$ git add first.txt 
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "第三次添加数据"
[dev 7ee2d8f] 第三次添加数据
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$

(3) 切换回master分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master 
Switched to branch 'master'
ubantu@ubantu-virtual-machine:~/git_folder$ 

(4) 准备合并dev分支,请注意–no-ff参数,表示禁用Fast forward:

ubantu@ubantu-virtual-machine:~/git_folder$ git merge --no-ff -m "禁用fast-forward合 并" dev 
Merge made by the 'recursive' strategy.
 first.txt | 1 +
 1 file changed, 1 insertion(+)
ubantu@ubantu-virtual-machine:~/git_folder$ 
  • 因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

(5) 不使用Fast forward模式,merge后就如下图
GIT分支管理_第13张图片

Bug分支


软件开发中,bug就像家常便饭一样。有了bug就需要修复,在git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

(1) 当你接到一个修复一个代号001的bug的任务时,很自然地,你想创建一个分支bug-001来修复它,但是,等等,当前正在dev上进行的工作还没有提交(模拟正在操作first.txt文件):

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b dev
ubantu@ubantu-virtual-machine:~/git_folder$ echo "add another data fouth" >> first.txt
ubantu@ubantu-virtual-machine:~/git_folder$ cat first.txt
this is my first data
this is my second data
this is my third data
this is my forth data
add one data
add another data in master
add another data
add another data second
add another data third
add another data fouth
ubantu@ubantu-virtual-machine:~/git_folder$ git status
On branch dev
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   first.txt

no changes added to commit (use "git add" and/or "git commit -a")
ubantu@ubantu-virtual-machine:~/git_folder$
  • 并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?

(2) git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作

ubantu@ubantu-virtual-machine:~/git_folder$ git stash
Saved working directory and index state WIP on master: 07a63f9 禁用fast-forward合并
HEAD is now at 07a63f9 禁用fast-forward合并
ubantu@ubantu-virtual-machine:~/git_folder$ 

(3) 首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建并切换到临时分支bug-001,加入出错内容位于first2.txt文件内:

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master 
Switched to  'master'
ubantu@ubantu-virtual-machine:~/git_folder$ git checkout -b bug-001
Switched to a new branch 'bug-001'
ubantu@ubantu-virtual-machine:~/git_folder$ 

(4) 现在修复bug,把 first2.txt文件first data commit 删掉,然后提交。

ubantu@ubantu-virtual-machine:~/git_folder$ cat first2.txt
first data commit
ubantu@ubantu-virtual-machine:~/git_folder$ cat first2.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git add first2.txt
ubantu@ubantu-virtual-machine:~/git_folder$ git commit -m "修复bug-001"
[bug-001 d63018d] 修复bug-001
 1 file changed, 1 deletion(-)
ubantu@ubantu-virtual-machine:~/git_folder$

(5) 修复完成后,切换到master分支,并完成合并,最后删除bug-001分支。

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout master
Switched to  'master'
ubantu@ubantu-virtual-machine:~/git_folder$ git merge --no-ff -m "修复bug-001" bug-001
 Merge made by the 'recursive' strategy.
 first.txt | 1 -
 1 file changed, 1 deletion(-)
Switched to a new branch 'bug-001'
ubantu@ubantu-virtual-machine:~/git_folder$ git branch -d bug-001
Deleted branch dev (was 7c13d45).

(6) 现在bug-001修复完成,是时候接着回到dev分支干活了!

ubantu@ubantu-virtual-machine:~/git_folder$ git checkout dev
Switched to branch 'dev'
ubantu@ubantu-virtual-machine:~/git_folder$ git status
On branch dev
nothing to commit, working directory clean

(7) 工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:

ubantu@ubantu-virtual-machine:~/git_folder$ git stash list
stash@{0}: WIP on master: 07a63f9 禁用fast-forward合并
ubantu@ubantu-virtual-machine:~/git_folder$ 
  • 作业现场还在,git把stash内容存在某个地方了,但是需要恢复一下.
ubantu@ubantu-virtual-machine:~/git_folder$ git stash pop
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   first.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (9e0bfcae9767c6e805a0243aaf7070464c1cfea0)
ubantu@ubantu-virtual-machine:~/git_folder2$ git status
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   first.txt

no changes added to commit (use "git add" and/or "git commit -a")
ubantu@ubantu-virtual-machine:~/git_folder$ 

小结:


  • 修复bug时,我们首先切换到出现bug的分支上面,然后创建新的bug分支进行修复,然后合并(最好禁止快速合并),最后删除;
  • 当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,恢复工作现场。

你可能感兴趣的:(Git版本控制)