七、多人协作
上文讲到多人协作,多人协作的基本原则是每个人在不同的分支branch上操作,代码通过测试之后再合并到master上面去。
(疑问:git add 与git remote add的区别是什么)
$git checkout -b branch1 #新建branch1
$git checkout master
$git checkout -b branch2
我们新建了两个branch,我们在两个分支上分别push一个文件上去
$echo "happy new year 2019">> log.txt
$git checkout branch1
$git add log.txt
$git commit --author="Bird Stone <stonebird0203@163.com>" -m "add happy new year"
#伪装成新的contributor “Bird Stone”
$git push origin branch1
$echo "happy new year 2018">> log.txt
$git add log.txt
$git commit -m "add happy new year 2018"
$git push origin branch2
现在gitlab的状态如下:
好,现在我们对两个分支上的修改都表示满意,需要merge到master去,当然我们可以用命令行,来merge:
$ git checkout master
$ git merge branch2
$ git push origin master
结果显示:
我们也可以在网页上操作merge
点击new merge request可以创建一个merge request按照提示将brach1合并进入master,此时我们发现由于branch1和branch2都是对log.txt文件进行了修改,出现冲突!下图界面中选择resolve conflict
下图可以看到冲突的内容:
这里我们可以选择采用任何一修改的版本,也可以选择采用 NanoApe 修改的版本,也可以选择 Edit inline 自己进行冲突的合并。 手动更改后,点击下面的 Commit 把冲突解决,然后点击 Merge 把修改合并到 master 分支。
本地的冲突解决方法,当使用git merge的时候会提示:
此时git status查看提示:
打开要修改的文件,进行编辑,<<<<<<< HEAD
表示冲突的开始,=======
表示两个文件之间的分割线>>>>>>> BRANCH-NAME
branch的来源
编辑之后
$git add .
$git commit -m "resolve conflict from branch2"
$git push
此时可以将编辑后的文件push到master中
好,目前为止我们做了一系列操作,包括网页上的直接操作,我们需要与gitlab的project同步,此时我们使用以下命令:
$ git pull origin master
#它不仅会拉取当前上游的提交,而且会把本地的 master 分支更 新到上游的版本。 不过,有时候,我们在本地更改了一些内容的时候,这个命令会 报错:因为你进行了修改,不允许你直接更新到上游的版本
$ git stash #它会把当前的更改保存为一个临时的 commit 并且回退到之前的 状态。之后当你想回到这个修改后的状态的时候,你可以
$ git stash apply # 它会尝试把你的更改应用过来,不过并不会删掉这个临时的 commit
# 你也可以选择
$ git stash pop #来应用并在成功的时候删除掉它。
# 如果要删掉全部的临时 commit , 你也可以
$ git stash clear
讲座中有一个启发性的例子,设想一下,你面临以下的情形:
- 有个图书馆,一开始没有书,经过了若干天后,有 3 本书
- 第一个人看中了一本书,想,今晚我要这本书。
- 第二个人想还一本书,想,今晚我把这本书还到这里。
- 到了晚上,图书管理员和这两个人⻅面了。他看了下第一个人要借书,拿去。第二个人要还书,嗯,放下。这时候 是 3 - 1 + 1 本书。
- 他记下:书 [0] A 借了;书 [3] B 还了
以上这个例子我们可以看做是三个状态的合并,原来的3本书;第一个人取走书后的2本书;第二个人还了书的3本书。
但是这个例子可能会出现冲突:
- 有个图书馆,一开始没有书,经过了若干天后,有 3 本书。
- 第一个人看中了一本书,想,今晚我要这本书。
- 第二个人也看中了这本书,想,今晚我要这本书。
- 到了晚上,图书管理员和这两个人⻅面了。他看了下第一个人和第二个人要借的书一样,唔,行,那我借出去了,但是给谁,你们自己打一架决定。
所以冲突的产生在于:不同人对同一个东⻄做了不同的更改, Git是怎么解决解决这个冲突的:三路合并(如下图所示)
从上面这个栗子我们可以看到,一些时候我们是可以很好地合并两个人的更改的。而这个更改,实际上就是,从两人的提交的最近的共同祖先到这两个提交的改变。通过把只有一方改变的地方合并起来,把双方都改变的地方要求用户去解决,这就是三路合并。 通俗的话说就是git会比较两次合并的冲突地方,然后交给用户决定(<<<<<<< 冲突内容>>>>>>>)。
八、关于分支
分支实际上就是一个一直跟随 commit 在变的标记。比如 master 分支,它代表着项目代码当前最新的一个提交。而 nanoape 分支,则代表 NanoApe 对代码更改的最新的一个提交。 实际上在合并的时候可以直接指定和哪个提交进行合并。 在真实的项目中,我们往往会进一步细分: develop 表示正在活跃开发的版本,release 表示已经发布的最新版本,等等。
分支的常见操作如下:
#创建一个新分支,它指向的 commit 为当前 commit
$ git branch [name]
#切换到指定的分支
$ git checkout [name]
#创建并切换到分支
$ git checkout -b [name]
#显示所有的分支
$ git branch
删除分支
$ git branch -d [name]
九、合并的其他策略
实际上,git还有其他合并的方法,例如rebase和squash。变基的意思就是在新的上游上重放你的更改。当然了,一样会有冲突的问题,但是最后的提交历史会是一条直线。Squash就是把你的更改全部合并成一个提交,再合并进去。
- rerere(Reuse recorded resolution)可以帮我们记录所有的冲突记录,然后当我们下次遇到同样的冲突的时候,它会自动帮我们解决。
$ git config --global rerere.enabled true
十、其他操作(略)
还有1个小时的是视频属于进阶版本,待后续补充。
十一、git diff patch的使用
设想一下这样的情形,你对一个文档进行了修改,在其他地方使用此处的修改。
生成patch
$ git diff > patch
$ git diff branchname --cached > patch //branch 之间差分生成patch文件
$ git format-patch HEAD^ //最近一次提交节点的patch
$ git format-patch 节点A 节点B //两个节点之间的patch
此时会生成一个新的文件patch
$git apply patch //将patch应用到本地2.在commit之后
我们一起开启git生涯吧!作为data engineering的起点!下一个任务是学习GNU Make!期待~