尽管 Git 是一个非常强大的工具,但是我相信大部分同学有时候学起 Git 来,感觉很难搞~ 笔者总是习惯于在脑海中重现学习的知识,Git 也一样:当我们执行了切换分支命令,分支之间是如何交互的?又是如何影响历史提交的?当我在 master
分支上执行了强制 reset
又 force push
到了远端 ,又把 .git
文件夹删掉,我的同事为什么会哭??
于是就有了将这些命令做成动画的想法!由于篇幅有限,本文主要覆盖一些常用命令的默认行为~
Merge | Rebase | Reset | Revert | Cherry-Pick | Fetch | Pull | Reflog |
---|
合并(Merging)
使用多个分支可以方便我们隔离彼此,也可以防止意外提交到生产环境,对分支模型感兴趣的小伙伴也可以看笔者之前的文章:
使用 git-flow 自动化你的 git 工作流
当我们的某个功能开发完成时,就需要将这些更改应用到生产环境上。其中一个应用的方式就是 git merge
!而这个命令有两种类型:一种叫 fast-forward
方式,一种叫 no-fast-forward
方式。
现在不太懂没关系,我们先来对比下这两个选项。
以下例子中将 master
称作 主分支 或 当前分支
Fast-forward (--ff
)
一个 fast-forward merge 可以被用于:当 主分支 相比 要被合并的分支 没有额外的提交时。Git 是。。懒惰的,它会首先尝试使用这个最简单的 fast-forward 选项。这种方式不会创建新的 commit,可以说它只是把我们的提交和 HEAD 指针挪了一个位置。
完美!现在我们所有的更改都从 dev
分支合并到 master
分支了~
No-fast-forward (--no-ff
)
主分支没有额外的提交当然是最好的情况,但是在多人协作的情况下,这种情况当然就很少见了,毕竟大家都在加班嘛~ 那么如果主分支具有额外的提交时,在 merge
时,git 就会使用 no-fast-forward
选项。
在使用 no-fast-forward
选项时,Git 就在当前分支创建了一个新的 合并提交。而这个提交的上一级同时指向了当分支和要合并的分支!具体见动图:
没啥大不了的,完美合并!现在 master
分支就包含 dev
分支中的所有提交了。
合并冲突(Merge Conflicts)
尽管 Git 对于合并的默认行为非常棒,但是总有需要我们自己解决的时候。比如说,当两个分支上都有新的提交,又同时修改了同一个文件同一行的内容,或者一个分支上删除了一个文件,而另一个分支却修改了那个文件等等。
这些情况下,Git 就会请我们来帮忙啦。假设我们在两个分支上同时修改了 README.md
文件。
如果我们想要将 dev
合并到 master
,这就会产生一个冲突(conflict):因为 Git 也不清楚你到底是想要 Hello!
还是 Hey!
?
所以当我们合并分支时,Git 会告诉我们冲突发生的具体位置。我们需要手动删除不要的地方,保存更改,然后再提交。
赞!尽管造成冲突非常烦人,但也符合逻辑,机器毕竟是机器,它肯定不能替我们决定需要保留哪块内容吧~
变基(Rebasing)
刚刚我们见识了 git merge
的合并过程。另一种将变更从一个分支应用到另一个分支的方式是:git rebase
。
关于这两个命令的区别也可以看笔者之前的文章:
带你理解 Git 中的 Merge 和 Rebase简单来说就是:Merge 保留历史记录,而 Rebase 改写历史记录
git rebase
将提交从一个分支(dev)复制到另一个分支(master)的顶部。
完美,现在我们已经将 dev
的起点设置为新的 master
分支了。
相比 Merge 来说一个很大的不同点是,Git 不会去查找哪个文件需要保留,哪个不需要。我们的 dev
分支可以使用 rebase 来一直追踪最新的 master
分支。这样就不会产生冲突,同时也会有一个线性的 Git 历史记录。
图中的例子是将 master
作为 dev
的 base (基础分支)
, 在大型项目中,通常我们不会这么做。git rebase
会修改项目的历史记录,同时复制的 commit 也会生成新的 hash 值。
当你在 feature
分支上工作,而 master
分支又更新了,这时就可以使用 rebase
,无缝地将 master
上的分支更新到你的 feature
分支了!
交互式变基(Interactive Rebase)
在进行变基之前,我们也可以修改之前的提交,这就用到了 交互式变基。交互式变基也适用于你想要修改当前工作分支的某些提交。
一共有 6 种操作可以应用到之前的提交上:
-
reword
:修改提交的信息 (commit message) -
edit
:修改提交内容 -
squash
: 将某个提交与前一个提交合并 -
fixup
: 同 squash,但是丢弃提交信息 -
exec
:在想要 rebase 的提交上依次执行某个命令 -
drop
: 删除某个提交
好啦!这样,我们就可以完全掌控我们的提交。如果你需要删除某个提交,只需要 drop
就好~
或者说如果我们为了干净的历史记录,需要合并多个提交,也没问题:
交互式变基给了我们很大的权力来控制提交,即使在你当前工作的分支也没问题。
未完待续
好啦,由于原文篇幅太长,本篇我们先讲了前两个命令:Merge 和 Rebase,这两个同时也是 Git 分支操作中最重要的两个命令,下一篇我们继续讲剩下的六个命令~
关注我了解更多哦~
参考文章
本文首发于公众号:码力全开(codingonfire)
本文随意转载哈,注明原文链接即可,公号文章转载联系我开白名单就好~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。