无论是数据科学家、算法工程师还是普通开发人员,在每个团队协作开发任务中,Git都是必不可少的版本控制工具,因此掌握它的基本操作十分有必要。但即便是教程满天飞的今天,开发人员在使用Git时也还是会犯一些不应该犯的错误。本文总结了其中的几种常见错误,希望能对新手有所帮助。
force push
有时,我们会需要用force push把commit推送到远端仓库。
假设有2名开发人员正在合作开发一个分支
之前开发人员1已经完成更改,把代码push到了远程仓库
现在,开发人员2也完成了更改,正当他准备提交时,他却发现自己无法将代码推送到远程仓库
由于开发人员2是个初学者,他Google了一下,发现了一个神奇的命令git push -f,于是进行了强制push
之后开发人员1在检查远程仓库时,发现自己编写的代码全消失了
出现这个问题的原因是force push会覆盖远程仓库中的代码,使现有代码全部丢失。
如果开发人员2想避免这个问题,一种理想方法是他先把开发人员1的更新从远程仓库pull到本地,然后把自己的代码rebase一下,再进行push。这里我们讨论的是在同一分支中从远程到本地仓库的rebase。
git push -f这个命令非常不安全,除非有绝对的必要,大家最好还是不要用它。它会把本地分支的提交覆盖远程推送分支的提交,给协作的同伴带去不少麻烦,即便是上面的解决方案,它也可能存在一个时间差的问题,因为你不可能时刻掌握同伴的工作进展。
所以如果大家都用正确的git工作流,让每个开发人员都拥有自己的功能分支,这种情况根本不会发生。
Rebase
如果你想把一个分支的修改合并到当前分支,你可以用git rebase。它和git merge的区别是merge有一个合并commit的步骤,而rebase是把所有commit都串联在一起,让你本地的分支历史看起来像没有经过任何合并一样。
假设有2名开发人员正在合作开发一个功能分支
开发人员1率先完成了一系列commit,并将其推送到远程功能分支
之后,开发人员2把远程功能分支的最新更改pull到本地
开发人员2向本地功能分支添加了一堆commit
这时,他想把本地仓库的更新重新rebase到远程仓库中,于是他把整个预发分支(release branch)在本地功能分支上rebase了一下。这里我们讨论的是在不同分支中从远程到本地仓库的rebase
现在,开发人员2试着把代码push到远程功能分支上,由于提交历史记录已更改,这个操作不被允许,他只能又开始用git push -f
最后,当开发人员1想从远程仓库提取最新代码时,由于提交记录已更改,他被迫需要处理大量代码冲突问题
常规rebase
开发人员2的操作
如上图所示,rebase远程仓库会改变提交历史记录,并在其他开发人员尝试从远程仓库中提取最新代码时产生问题。处理这种情况的理想方法是始终只rebase本地仓库,本地仓库中的任何commit都不应该被push到远程仓库。
如果别人事先已经把commit推送到远程功能分支,那么你最好先用pull命令把更新拉到本地,用merge和你的修改合并,因为merge不会改变提交历史,而rebase会。
此外,和上个问题一样,如果使用正确的git工作流,每个开发人员都会有自己的功能分支,这时,开发者在自己的功能分支上进行更新并且在远程功能分支上做rebase是不会报错的,因为没有其他开发人员从同一个远程功能分支中提取代码。无论如何,尽量避免重新定义远程仓库。
Rebase是一个非常强大的功能,使用时也需谨慎。
amend
git amend命令的作用是修复最近一次commit,让你合并你缓存区的修改和上一次commit,而不是提交一个新的快照。这里需要注意一点,它不是修改最近一次commit,而是整个替换掉原commit,所以对Git来说这是一个新的commit。此外,它还可以用来编辑上一次的commit描述。
假设有2名开发人员正在合作开发一个功能分支
开发人员1率先完成了commit,并将其推送到远程功能分支,我们把它称为“old commit”
之后,开发人员2把最新代码从远程功能分支pull到本地功能分支
然后他开始处理本地仓库中的代码,在这个过程中,他没有向远程仓库push任何commit
这时开发人员1突然发现之前的commit中存在bug,他用amend命令修复了本地仓库里的最近一次commit,我们把它称为“new commit”
开发人员1尝试把这个新commit重新push到远程功能分支,由于提交历史记录发生了变化,这个操作报错了,于是他调用了git push -f
现在,当开发人员2想从远程功能分支中提取最新代码时,git会注意到提交历史记录的变化并创建合并的commit。因此当他pull到本地后,他会在本地仓库里发现“commit old”和“commit new”,这就破坏了amend这个操作的意义。
最后,即便开发人员2从远程分支到本地分支执行rebase,这个“commit old”还是会出现在本地仓库中,它仍然会作为历史提交的一部分。
amend commit会更改提交历史记录,所以当其他开发人员尝试从远程仓库提取最新代码时,修改远程仓库中的commit会产生混淆。
为了避免这个错误,最好的方法是只在本地仓库里修改commit,不要对远程库里的commit做任何修改。当然,一人一个分支也不会出现这个问题。
Hard reset
git reset命令是用来将当前branch重置到另外一个commit的。它不会产生commit,而是只更新一个branch(branch本身就是一个指向一个commit的指针)指向另外一个commit。
Hard reset的命令是git reset --hard
此外,git reset还有--soft和--mixed,只不过它们都没有Hard reset那么不安全
假设开发人员1正在开发一个功能分支,并在本地仓库中完成了5次commit
与此同时,他还正在处理尚未提交的两个文件
这时,如果他运行了git reset --hard
那么功能分支中的最新commit会变成是commit4,commit5丢失
同时他正在处理的那两个未提交文件也会丢失
这时commit5还在git内部,只不过对它的引用丢失了,我们可以用git reflog把它恢复,但总体来说,hard reset还是很不安全。在git中使用reset命令时要非常小心,如果必须得用,确保你已经完全评估所有情况。
小结
综上所述,为了避免使用git时出错,我们可以牢记这几条教训:
避免多人在同一分支上协作。上述四个例子中有三个都是在说明这个问题,在日常工作中,遵守正确的工作流非常重要,要确保只有一个人在一个功能分支上工作,这是技术主管、高级开发人员尤其需要注意的。
不要到处实用force push。
如果万不得已必须使用force push,先评估其他方案,把它作为最后的手段。
不要试图修改远程仓库里的commit,要只在本地仓库中更改commit历史记录。但即便是在本地仓库里,用rebase还是要谨慎。
-
代码
+关注
关注
30文章
4788浏览量
68625 -
Git
+关注
关注
0文章
200浏览量
15765
原文标题:实用:Git中的一些常见错误
文章出处:【微信号:jqr_AI,微信公众号:论智】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论