实用:Git 中的一些常见错误
无论是数据科学家、算法工程师还是普通开发人员,在每个团队协作开发任务中,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远程仓库会改变提交历史记录,并在其他开发人员尝试从远程仓库中提取最新代码时产生问题。处理这种情况的理想方法是始终只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 <commit4hash>
那么功能分支中的最新 commit 会变成是 commit4,commit5 丢失
同时他正在处理的那两个未提交文件也会丢失
这时 commit5 还在 git 内部,只不过对它的引用丢失了,我们可以用 git reflog 把它恢复,但总体来说,hard reset 还是很不安全。在 git 中使用 reset 命令时要非常小心,如果必须得用,确保你已经完全评估所有情况。
小结
综上所述,为了避免使用 git 时出错,我们可以牢记这几条教训:
避免多人在同一分支上协作。上述四个例子中有三个都是在说明这个问题,在日常工作中,遵守正确的工作流非常重要,要确保只有一个人在一个功能分支上工作,这是技术主管、高级开发人员尤其需要注意的。
不要到处实用 force push。
如果万不得已必须使用 force push,先评估其他方案,把它作为最后的手段。
不要试图修改远程仓库里的 commit,要只在本地仓库中更改 commit 历史记录。但即便是在本地仓库里,用 rebase 还是要谨慎。
原文地址:adityasridhar.com/posts/how-you-can-go-wrong-with-git
实用:Git 中的一些常见错误的更多相关文章
- git常用命令图解 & 常见错误
Git 常用命令 基本命令 git clone.这是一种较为简单的初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份 git clone git://github.com/someon ...
- 菜鸟学git的基本命令及常见错误
Git init //在当前项目工程下履行这个号令相当于把当前项目git化,变身!\ git config --global user.name "xxx" # 配置用户名 git ...
- Git远程推送常见错误及解决方案:
Git远程推送 关注公众号"轻松学编程"了解更多. 1.问题:git远程提交时出现错误: error: RPC failed; curl 56 OpenSSL SSL_read: ...
- Java中的一些常见错误
1.空指针错误 在java数组的使用中,有时候需要对字符串数组中的元素进行对比.那么当元素不为null时,程序会正常运行:然而,一旦对比的元素为null,那么程序就会出现空指针错误. 解决方法:加入保 ...
- php中sql语句常见错误
.php文件中sql语句的写法导致的错误如下: 1.$logSql="select * from jd_login where uname=".$u."and upwd= ...
- Latex 1: 解决latex中遇到一个常见错误:"Improper alphabetic constant."
1.问题: 本人是在WIN7下用texlive 2016,编辑器用的是WinEdt 10.1 ,运行如下代码: \documentclass{ctexbook} \begin{document} \t ...
- solr中的一些常见错误
(1)Caused by: java.lang.ClassNotFoundException: Unable to load jdbcDataSource or org.apache.solr.han ...
- Vue实践TS中的一些常见错误解决方案
mixin报错 import { Component, Prop, Vue ,Mixins} from 'vue-property-decorator' import httpminix from ' ...
- javaweb开发中的常见错误
Javaweb中的最常见错误及其解决方法 1.200:表示成功处理业务. 2.400 请求出错: 由于语法格式有误,服务器无法理解此请求.不作修改,客户程序就 无法重复此请求. 解决办法:,遇到400 ...
随机推荐
- sqlserver 3145
参考链接:http://www.uoften.com/dbs/mssql2005/20180415/73780.html 第一步:查询 use master;--用此语句得到备份文件的逻辑文件名RES ...
- 装了SVN软件,但是文件夹没有绿色和红色的图标显示
第一步: win+R,输入regedit,打开注册表.查找ShellIconOverlayIdentifiers,可以找到Tortoise相关的标签,这个时候会发现,这些标签都排在后面.需要在这些标签 ...
- centos 下使用vscode 调试egg.js 注意事项
这两天在centos下,直接用vscode运行egg.js的例子.遇到个问题就是当安装了vscode-egg插件,会遇到一个现象.就是同样的代码,Windows下调试可以顺利进行,但是centos有时 ...
- PowerDesigner code、name显示设置 及 同时显示办法
菜单->Tool->Model Options->Name Convention->右侧display中选择显示name还是code. 不支持同时显示,但可以选择显示code, ...
- SpringCloud(一)Eureka注册中心
Eureka简介 Eureka作为注册中心,管理各种服务功能包括服务的注册.发现.熔断.负载.降级等 Eureka注册中心实例 Eureka Server 1.pom文件配置SpringBoot.Sp ...
- MySql共享锁和排它锁
共享锁和排他锁 1.共享锁: 读锁.X锁,在查询时生效,多个事务在查询同一个数据时共享一把锁,但是不能作用于修改数据,在select语句后添加 lock in share mode : 2.排他锁:在 ...
- zabbix3.0监控Windows服务器
我们下载后,解压开始有多个文件: conf目录存放是agent配置文件bin文件存放windows下32位和64位安装程序 找到conf下的配置文件 zabbix_agentd.win.conf ,修 ...
- godoc
Godoc-一个Go代码文档化工具 Python - Docstring Java - javadoc
- SQL视图命名规则:一般以V_xxx_xxxxxx
- Maven学习 七 Maven项目创建(2)war项目
一.web项目的目录结构 如果手动创建一个java web项目,其基本的目录结构包括:METE-INF,WEB-INF,以及WEB-INF下必须包含一个web.xml文件 二.使用Maven创建wa ...