0


git fetch, git pull, git merge, git rebase

背景:

我们发现很多同学习惯性用git pull拉取远端仓库代码,

但是这会带来一个问题,如果有了本地commit再git pull的话,会产生一个merge commit,

这样的merge commit会导致git log分支节点很多,很乱。

首先聊一聊git pull,git merge,git rebase这些常听到的命令吧,初入git的同学一定还是一脸蒙,尤其是git rebase,算是git的中高阶操作了。

git fetch, git pull, git rebase

1. git fetch和git pull

git pull = git fetch + git merge

git pull

的过程可以理解为:

git fetch origin master //从远程主机的master分支拉取最新内容 
git merge FETCH_HEAD //将拉取下来的最新内容合并到当前所在的分支中

将远程主机的某个分支的更新取回,并与本地指定的分支合并,完整格式可表示为:(默认的远程主机别名为origin)

$ git pull <远程主机别名> <远程分支名>:<本地分支名>

如果远程分支是与当前分支合并,则冒号后面的部分可以省略:

$ git pull <远程主机名> <远程分支名>

2. git merge

有一个远程仓库origin:

本地在此基础上又进行了两次提交:

这时候其他人进行了一次远程push:

因为git是分布式的,原则上可以不用连服务器,所以此时本地并不知道远程分支已经变更(本地的origin/master已经过时):

git fetch命令会将远程最新的版本拉取到本地,但是并不会影响本地的分支线:git fetch <远程主机名> <远程分支>

git merge会将本地和远程的最新提交混合起来,并生成新的最新提交(混合并解决冲突后的提交):

git pull命令等于git fetch + git meger命令。


3. git rebase

我们再看下上面git fetch命令后的本地状态:

这时候我们并不想混合提交,而是想在C2的基础上直接提交L2和L3,这时候在提交历史线上不会有分支线。这个可以用git rebase命令实现:

rebase(换基命令)说明:

git rebase origin/master #将当前分支换基到origin/master指向的分支。具体为先将本分支的提交全部暂存,然后从origin/master指向的分支开始依次应用暂存的提交,若出现冲突会要求解决,解决后用git add暂存,然后git rebase --continue继续,直到解决完所有冲突,换基操作完成。
git rebase origin/master dev #将dev分支的所有提交换基到origin/master指向的提交

4. git pull vs git pull --rebase

git pull

git pull --merge

的简写。

git pull

git pull --rebase

的关系如下:

git pull = git fetch + git merge
git pull --rebase =  git fetch + git rebase

可以看出merge和rebase的区别:

  • merge 会多出一次 commit生成一个新节点,rebase不会。
  • merge 的提交树是非线性的,rebase 的提交树是线性的(通过重写提交历史)。

遇到的问题和使用场景

当我在提议开发同学平时使用git pull --rebase来更新代码时,却遇到了几个问题:

1)git rebase会导致时间日志时间错乱。

git merge会按照时间顺序进行commit的排练,但是git rebase会把本地的提交直接变基到当前最新,所以会导致老的提交

在当前最新的提交前面。

2)git rebase时本地不能有未提交的文件

当本地有未暂存的文件时,git rebase会报error。

$ git pull --rebase
error: cannot pull with rebase: You have unstaged changes.
error: please commit or stash them.

但是使用git pull却不会报错。

这个时候我们或者要提交文件,或者用git stash

git stash # 存储工作区
git pull --rebase  # 更新代码
git stash pop # 恢复工作区

3)git rebase时冲突解决

会出现如下报错:

error: could not apply fa39187... something to add to patch A  
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
Could not apply fa39187f3c3dfd2ab5faa38ac01cf3de7ce2e841... Change fake file

步骤:

a) 修改冲突文件:打开冲突文件,搜索:<<<<<< ,git 会用<<<<<<,======,>>>>>>>把冲突的部分标记出来,你可以选择保留某些行,或者删除,或者更改。记得把<<<<<<<, =======, >>>>>>>这些删除掉。

b) 解决完冲突后,执行git add命令标记冲突已解决

c) 继续rebase:git rebase --continue (后续的过程中还有可能产生冲突,解决方法同上)

所以,当本地commit很多时执行git rebase是一件比较痛苦的事情。

总结

综上,我们还是根据不同的场景合理的使用git pull 和 git pull --rebase。

我目前给开发同学的建议是:本地有单个commit时建议用git pull --rebase, 本地有多个commit时建议用 git pull。

对了,前提条件是,远端仓库是可以直接push的,而不是gerrit的那种push成code-review的那种。

如果是gerrit上要生成code-review,那么必定是要使用git pull --rebase的。

标签: git github

本文转载自: https://blog.csdn.net/zhulianseu/article/details/129841801
版权归原作者 送你一朵小莲花 所有, 如有侵权,请联系我们删除。

“git fetch, git pull, git merge, git rebase”的评论:

还没有评论