手记

分布式版本控制系统 Git | 七

分布式版本控制系统


Git分支


分支简介

注意Git分支的内容,我们要先了解Git保存的不是文件的变化或差异,而是一系列的不同时刻的文件快照。

Git在进行提交操作的时候,会保存一个提交对象(commit object)。这个提交对象包含一个指向临时存储内容快照的指针,还包括提交者的姓名,邮箱,提交的信息以及指向它的父对象其他普通提交操作产生的对象都有一个父对象,当多个分区合并产生的提交对象则有多个父对象。

分支创造与合并

上面的文章中,我们提到每次提交,GIT中指向它们串联成一条时间线,这时间线就是一个分支。未新建分支之前,这个就是主分支,即是分支。

Git如何创建新分支?使用git branch <branch_name>,这里它会创建一个可以移动的新指针。

$ git的分支dev的```


这时,便会在提交对象上创建一个指针,如下图:

![图1](https://i.loli.net/2020/02/09/LRMpFnuhxt9NsJC.png)

现在创建了一个分支,但是混帐如何分辨两个分支,如何知道目前在哪个分支?这里要提及一个特殊指针` HEAD `。

` HEAD `严格来说不是指向提交,默认情况下,而是指向`主`,而`主`或者新创建的` dev的`才是指向提交,` HEAD `指向的就是当前分支。刚才` GIT中分支开发`仅仅是创建了一个新分支,并不会自动切换到新分支上去。

![图 2](https://i.loli.net/2020/02/09/pnuX6mJrzsGfevk.png)

HEAD 指向的是当前所在的分支,可以使用命令 `git log` 查看各个分支当前所指的对象。配合参数 `--decorate`:

```code
$ git log --oneline --decorate
861b17e (HEAD -> master, dev) Initial commit of project

此时,masterdev分支均指向校正和为初始861b17e的提交对象。

切换分支

切换已经存在的分支,可以使用git checkout <branch>或者git switch <branch>,这里使用的是git switch更容易理解:

$ git switch dev
Switched to branch 'dev'

这样HEAD就指向了dev分支。

Git还提供一个命令能够创建的同时切换到分支:

$ git switch -c iss007

或者

$ git checkout -b iss007

使用带-c参数的GIT中开关命令,或者使用带-b参数的结帐命令。

其实上面的命令可以分解为:

$ git的分支iss007 
$ git的开关iss007 $ git的分支iss007 $ git的结帐iss007 ```





假设现在在` iss007 `分支上工作,并做了提交。在这个过程中,` iss007 `分支会不断向前推进。

```代码
$ VIM发行
$ git的承诺-a -m “修复问题007 [问题007]” ```


![图4](https://i.loli.net/2020/02/09/5OYUiPpcM4jEbXf.png)

假设,这个时候有另外一个紧急的问题需要解决。使用 Git 这个时候不需要将这个问题跟 issue 007 混合在一起。也不用去还原关于 iss007 的修改,再添加关于这个紧急问题的修改,只需要需要回到 `master` 分支,创建新分支解决紧急问题。

这里需要注意,切换到 `master` 分支之前,需要留意工作目录和暂存区有没有未提交的文件,它会检测出分支冲突阻止切换分支(待会介绍这种情况)。这里假设工作目录是干净的:

```code
$ git switch master
Switched to branch 'master'

$ git switch -c hotfix
Switched to a new branch 'hotfix'
$ vi ISSUE
$ git commit -a -m "fixed the hot issue"

现在紧急问题已经修复,这个时候就可以合并回master分支部署到线上,如下:

$ git switch master 
$ git merge hotfix 
更新861b17e..48a6cfa 
快速转发
问题| 1 + 
1的文件更改时,1个插入(+)
创建模式100644问题“ !! [branch_img_6.jpg](https://i.loli.net/2020/02/09/YusZcQIDdCVJ8wl.png)注意”快进',这个表示的是“快速模式”,也就是直接将主指向修补程序的当前提交,合并速度快。**注意:**,并非所有的合并皆“快进`。同时,我们可以删除``修复分支,因为已经完成任务了:`''代码$混帐的分支-d修补程序。删除分区修补程序(为48a6cfa)``` ####解决冲突现在紧急的问题已经修复部署上[图7](https://i.loli.net/2020/02/09/PtesZyibFfkRKIz.png,图,可以回到`iss007`分支继续修改文件。假设`iss007`分支也经过修改解决了问题。! )这个时候也考虑合并会主部署到线上:```代码$ git switch master $ git merge iss007 CONFLICT(添加/添加):ISSUE 自动合并中的合并冲突ISSUE 自动合并失败;解决冲突,然后提交结果。```































这个时候会出现合并冲突,因为 iss007 分支与 hotfix 分支修改的是同一个文件。Git 不会自动创建新的合并提交。需要手动解决冲突之后再提交。

使用 `git status` 查看处于未合并状态的文件:

```code
$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both added:      ISSUE

no changes added to commit (use "git add" and/or "git commit -a")

现在查看冲突的文件:

<<<<<<< HEAD 
修复热点问题。
======= 
修复问题007。
修复问题继续并完成。
>>>>>>> iss007 ```


Git用` <<<<<<< `,` ======= `,` >>>>>>> `标记出不同分支的内容,修改内容如下:

```代码
修复热点问题。
修复问题007。
修复问题继续并完成。```


将标记的部分删除,根据需求解决冲突,然后用` git的附加`将其标记为冲突已解决。

```代码
$ git add ISSUE $ git status 在分支主机上所有冲突已修复,但您仍在合并。  (使用“git的承诺”缔结合并)更改为承诺:        修改:问题```










这个时候就可以提交部署了:

```code
git commit -a -m "Merge branch 'iss007'"
[master 7059dd0] Merge branch 'iss007'

分支管理策略

的Git分支除了创建和删除分支不加参数时,命令能够得到所有分支的列表:

$ git的分支
  开发
  iss007 
*主```


` * `号表示当前的分支(即使` HEAD `指针指向的分支)。

加上` -v `参数也可以查看每个分支最后的提交信息:

```代码
$ git的分支-v 
  开发861b17e初始提交项目
  iss007 5267039修复问题007再次
*主7059dd0合并分支'iss007' ```


`git branch` 命令还有两个选项 `--merged` 和 `--no-merged`。这两个选项分别过滤合并或尚未合并到当前的分支。

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

```code
$ git branch --merged
  iss007
* master

因为已经合并过·iss007`,所以这个时候也可以删除该分支,这里并不会丢失任何东西:

$ git的分支-d iss007 
删除分支iss007(为5267039)。```


查看所有包含未合并工作的分支,可以使用` git的分支--no-合并`:

```代码
$ git的分支--no归并
  开发```


这里显示了dev分支,它包含了尚未合并的工作,现在尝试使用删除命令会运行失败:

```code
$ 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'.

如果真的想要删除这些未合并的工作,可以根据下面的提示,使用-D选项强制删除。

抓取分支

多人协作的情况下,大家都会往dev的分支推送各自的修改。

但是当协作者修改的是同一个文件,且先一个提交到远程仓库时,这个时候,当你修改完问题提交的时候,就会提示冲突。

解决办法:用git的拉抓取文件,在本地合并解决冲突再推送即可。

这里参考上面冲突解决的步骤就可以可以。

变基(Rebase)

每次合并再推后,分支会变得混乱。

Git有一种成为rebase的操作,能够让Git的提交历史变成直线。

这里我用之前学习的示例来体现说明。

和远程分支同步后,对文件打算两次提交,用git log查看:

* 24be579 (HEAD -> master) add author
* 94448fe add comment
* 6a7291a store Git Learn
* e36f4e9 (origin/master) add content about co-operative and update catalog
* 6cd4087 add knowledge about feature branch

注意到Git用(Head -> master)(origin/master)标识当前分支的HEAD和远程origin的位置分别是24be579 add authore36f4e9 add content..,本地比远程分支快3个提交

现在尝试推出本地分支:

$ git push origin master
To github.com:username/git_learn.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:username/git_learn.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

失败了,说明有人先往远程库推进了分支。先pull一下

$ git pull
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:damengsanqianqiu/git_learn
   e36f4e9..538bd7c  master     -> origin/master
CONFLICT (add/add): Merge conflict in hello.py
Auto-merging hello.py
Automatic merge failed; fix conflicts and then commit the result.

这里自动合并失败,手动解决冲突(详情略)。

解决冲突,再提交。再用git status查看状态

$ git的状态
分支主
你的分支进取“的由来/主”的4个提交。
  (使用“混帐推”发布您的本地提交)```



加上先前合并的提交,现在我们分支比远程分支超前4个提交。

用` git的日志`看看

```代码
$ git的日志--graph --pretty = ONELINE --abbrev提交
* 2027993(HEAD - >主站)hello.py的修复冲突
| \   
| * 538bd7c(来源/主邮件)设置退出= 1 
* | | 24be579添加作者
* | 94448fe添加评论
* | | 6a7291a商店Git Learn 
| /   
* e36f4e9添加有关合作社的内容并更新目录```


现在分支比较乱,这个时候,rebase 就派上用场了,用 `git rebase` 试试:

```code
$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py

再用` git的日志’看看,

`代码
$ GIT登录–graph --pretty = ONELINE --abbrev提交

  • 2027993(头戴式>主)修复hello.py冲突
  • 24be579添加作者
  • 94448fe添加注释
  • 6a7291a存储GIT中了解
  • 538bd7c(原点/原版)设置出口= 1 原来分叉的提交现在变成一条直线。我们注意到GIT中把我们本地的提交“挪动”了位置,放到了538bd7c(原点/主)组出口= 1 之后,这样整个提交历史就成了一条直线.rebase操作前后,最终的提交内容是一直的,但是,本地的承诺修改内容已经变化了,他们的修改不再基于e36f4e9添加内容... ,基本上基于538bd7c(原点/主)组出口= 1 ,但最后的提交2027993分叉的提交历史“整理”成一条直线,看起来更直观。相反就是本地的分叉提交已经被修改过了。

关于变基与合并,这里会有不同的观点,有的发现提交历史就是记录发生过什么,使用变基取代痕迹抹除,另外的观点会觉得提交历史就是项目过程发生的事情,没人在意第一版的手稿,大部分手册也是多次修订后才能方便使用。这里并没有必要追究一个完整简单的答案。需要根据实际情况去决定做出选择。不过,总体的原则是,尚未推进或分享的本地修改,可以根据情况执行变基清理历史,已推送到别处的提交,不要执行变基操作- > 以上就是本篇的主要内容。 -但是,这些内容能够让你简单了解GIT中,也希望这些内容这里若是希望更深入了解Git的使用可以查看官方文档:[ https://git-scm.com/ book / zh / v2](https:// git-scm。 com / book / zh / v2

1人推荐
随时随地看视频
慕课网APP