如何让你的 Git 历史保持“干净”?!

640?wx_fmt=gif

消除 Git 历史的最佳手段有哪些?

640?wx_fmt=jpeg

作者 | Manuel Sidler

译者 | 谭开朗,责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

以下为译文:

使用Git已有几年的时间了,我必须承认,干净的提交历史并不总是那么重要。我们从《回到未来》中知道,改写历史可能会造成某些糟糕的后果。我只能假设,这就是为什么这是一个可怕的话题。在这篇文章中,我想分享一些基本的命令,这些命令将帮助你保持Git历史的整洁,并消除《回到未来》中的糟糕后果。

 

640?wx_fmt=png

要事第一

 

本文中的所有命令都将生成新的提交哈希码,从而将其与原始分支区别开来。这意味着,你必须使用git push -force或git push -f强制覆盖远程上的历史记录。这又意味着:永远不要更改共享分支上的git历史记录。如果远程分支有新的提交,则有一个更安全的命令,它甚至可以拒绝强制推送:git push –force-with-lease。

 

640?wx_fmt=png

场景1:在最后一次提交中添加内容

 

每个人都有过这样的经历:将改动添加到暂存区,提交并等待构建。但不幸的是,构建失败了。哦,你忘了添加文件x。接下来会发生什么?将文件x添加到暂存区,并提交一条类似于“愚蠢的我忘了添加文件x”的内容。请不要这么做!让我来介绍第一个命令:

git commit -amend

该命令将暂存区的改动添加到最近一次提交,并支持更改最近一次的提交内容。使用以下简单的命令也能达到相同的效果:

git commit –amend -m“new message”

如果不想修改最后的提交信息,可以添加no-edit参数:

git commit --amend --no-edit

所以不要再犯“愚蠢的我忘了…”的错误了!

 

640?wx_fmt=png

Git的交互式rebase

 

在接下来的几个场景中,我们将使用交互式git rebase。这个工具能帮助修改历史上更早的更改。只需使用以下命令启动一个交互式rebase:

git rebase –i <base>

其中<base>表示要重写历史的节点。

例如,重写最后三次提交:

git rebase -i HEAD~3

另一个例子,重写历史到一个特定的提交:

git rebase -i 63a2356

该命令显示了配置编辑器的提交和选项:

pick bcfd87e add sql scripts for database
pick 9fb0b9c prevent users from changing their email
pick e0b46b9 cleanup web config

# Rebase dfef724..e0b46b9 onto dfef724 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

让我们进入第一个rebase场景。

 

640?wx_fmt=png

场景2:向历史记录中的任意提交添加内容

 

就像在场景1中,我们忘记在提交中添加内容。但是,与其添加到最后一次提交中,不如将改动修改为历史上更远的一次提交。对于这种情况,交互式rebase为我们提供了编辑选项。

我们从交互式rebase命令开始,然后在我们想要更改的提交上设置编辑命令:

pick bcfd87e add sql scripts for database
edit 9fb0b9c prevent users from changing their email
pick e0b46b9 cleanup web config

交互式rebase停止此提交,我们可以添加更改:

Stopped at 9fb0b9c...  prevent users from changing their email
You can amend the commit now, with

  git commit --amend 

Once you are satisfied with your changes, run

  git rebase --continue

完成后,只需将更改添加到暂存区,并使用amend命令提交:

git commit --amend

几乎完成了!现在我们要continue rebase:

git rebase –continue

 

640?wx_fmt=png

场景3:合并提交

 

尽量多做合并。这意味着功能分支中的git历史记录通常是这样的:

9edf77a more review findings
67b5e01 review findings
940778d enable users to change their name
dc6b0db enable users to change their name
dfdd77d wip

这在特性开发期间可能很有用,但并不适用于整个git存储库历史。因此将所有提交合并为一个。有两种方式:squash和fixup。这两个命令都是将提交合并到前一个命令中。唯一的区别是,squash支持编辑新的提交内容,而fixup不支持。

我们来squash一些提交。我们像之前一样启动交互式rebase,并设置适当的选项:

pick dfdd77d wip
squash dc6b0db enable users to change their name
squash 940778d enable users to change their name
squash 67b5e01 review findings
squash 9edf77a more review findings

# Rebase 63a2356..9edf77a onto 63a2356 (5 commands)

现在Git提供了所有消息的概览:

# This is a combination of 5 commits.
# This is the 1st commit message:

wip

# This is the commit message #2:

enable users to change their name

# This is the commit message #3:

enable users to change their name

# This is the commit message #4:

review findings

# This is the commit message #5:

more review findings

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

删除所有行,只将我们想要的信息写在最后:

enable users to change their name

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

瞧,把提交压缩成一个了:

cb88cf6 enable users to change their name

我们可以使用fixup命令执行同样的操作。在下面的场景中,提交消息很完美,我想把提交合并到:

pick dc6b0db enable users to change their name
fixup dfdd77d wip
fixup 940778d enable users to change their name
fixup 67b5e01 review findings
fixup 9edf77a more review findings

# Rebase 63a2356..9edf77a onto 63a2356 (5 commands)

结果和上面squash的例子一样:

b8e76d1 enable users to change their name

640?wx_fmt=png

场景4:分割提交

 

我们常常把两个或两个以上不同的主题合并在一起:

7080968 add sql scripts for database
172db2b prevent user from changing their email and cleanup web config

在这种情况下,将web配置的清理分离出来会更干净,对吧?此时,我们可以再次利用edit命令。使用互动rebase可做到这一点:

pick 7080968 add sql scripts for database
edit 172db2b prevent user from changing their email and cleanup web config

# Rebase dfef724..172db2b onto dfef724 (2 commands)

正如我们所期望的,Git在提交时停止了。现在我们可以把更改带回工作区域:

git reset HEAD~

接下来很简单,只需为更改创建两个提交:

git add [files]
git commit -m "prevent user from changing their email"
git add [files]
git commit -m "cleanup web config"

别忘了继续rebase:

git rebase --continue

结果如下:

9fb0b9c prevent user from changing their email
dfef724 cleanup web config
7080968 add sql scripts for database

多整洁!

 

640?wx_fmt=png

场景5:重新排序提交

 

如果合并两个或多个提交,但它们的顺序不对怎么办?

09f43c9 validate user inputs
62490ed import user data
c531f57 validate user inputs

只需在rebase编辑器中重新排序提交,然后再使用fixup或squash合并它们。

pick 62490ed import user data
pick c531f57 validate user inputs
fixup 09f43c9 validate user inputs

# Rebase 6c70ff2..09f43c9 onto 6c70ff2 (3 commands)

 

640?wx_fmt=png

场景6:更改提交消息

 

不满意特定的提交内容?可以使用reword命令随时更改它:

reword c531f57 validate user inputs
pick 62490ed import user data

# Rebase 6c70ff2..09f43c9 onto 6c70ff2 (3 commands)

Git将在此时停止提交,我们可以选择更改消息: 

validate user inputs

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

 

640?wx_fmt=png

场景7:删除提交

 

需要完全恢复特定的提交吗?在这种情况下,我们可以使用drop命令:

pick bcfd87e add sql scripts for database
drop 9fb0b9c prevent users from changing their email
pick e0b46b9 cleanup web config

# Rebase dfef724..e0b46b9 onto dfef724 (3 commands)

在这里,我们知道了保持Git历史记录整洁的重要性。假设我们将不同的特性放入一个提交中,或者将一个特性拆分为多个(无意义的)提交,那么还原要复杂得多。 

 

640?wx_fmt=png

当事情出现问题时

 

在重写Git历史时,不要担心会破坏某些东西。

首先,我们总是可以使用git rebase--abort中止交互式rebase会话。 

这个命令将停止rebase会话并恢复所有更改。

其次,即使已经完成了一个rebase并把它搞砸了,我们也可以还原它。幸运的是,Git跟踪执行所有命令,我们可以使用git reflog打开日志。

e0b46b9 (HEAD -> feature/my2, feature/my3) HEAD@{34}: rebase -i (finish): returning to refs/heads/feature/my2
e0b46b9 (HEAD -> feature/my2, feature/my3) HEAD@{35}: commit: cleanup web config
9fb0b9c HEAD@{36}: commit: prevent users from changing their email
bcfd87e HEAD@{37}: reset: moving to HEAD~
3892bc7 HEAD@{38}: rebase -i: fast-forward
bcfd87e HEAD@{39}: rebase -i (start): checkout master
3892bc7 HEAD@{40}: rebase -i (finish): returning to refs/heads/feature/my2
3892bc7 HEAD@{41}: commit (amend): prevent user from changing their email and cleanup web config
39262b5 HEAD@{42}: rebase -i: fast-forward
bcfd87e HEAD@{43}: rebase -i (start): checkout master
39262b5 HEAD@{44}: rebase -i (abort): updating HEAD
39262b5 HEAD@{45}: rebase -i (abort): updating HEAD
bcfd87e HEAD@{46}: reset: moving to HEAD~
39262b5 HEAD@{47}: rebase -i: fast-forward
bcfd87e HEAD@{48}: rebase -i (start): checkout master
39262b5 HEAD@{49}: rebase -i (finish): returning to refs/heads/feature/my2
39262b5 HEAD@{50}: rebase -i (pick): prevent user from changing their email and cleanup web config
bcfd87e HEAD@{51}: commit (amend): add sql scripts for database
7080968 HEAD@{52}: rebase -i: fast-forward
dfef724 (master) HEAD@{53}: rebase -i (start): checkout master
172db2b (feature/my) HEAD@{54}: checkout: moving from feature/my to feature/my2
172db2b (feature/my) HEAD@{55}: commit: prevent user from changing their email and cleanup web config
7080968 HEAD@{56}: commit: add sql scripts for database
dfef724 (master) HEAD@{57}: checkout: moving from master to feature/my
dfef724 (master) HEAD@{58}: commit (initial): init

我们可以找到交互式rebase会话之前的最后一个操作,并将其恢复状态。例如:

git rest—hard HEAD@{18}

所以,请战胜恐惧,并保持Git历史的干净吧!

原文:https://dev.to/manuelsidler/keep-your-git-history-clean-101-k7

本文为 CSDN 翻译,转载请注明来源出处。

【END】

Python的C位稳了!微软正式拥抱Python !

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

随着智能物联迅速的兴起,场景联动越来越普遍,作为敲门砖的连接服务该如何实现?

360 资深工程师深度揭秘 360 IoT 云平台连接服务的技术框架实现细节、物联网协议应用和多协议,多网络的落地实践以及连接服务未来的演进方向。

技术干货来袭!立即扫码报名!

640?wx_fmt=jpeg

 热 文 推 荐 

 

☞马云卸任阿里巴巴董事局主席;苹果承认违法中国劳动法;IntelliJ IDEA 2019.2.2 发布 | 极客头条

☞微软发布IoT应用现状报告:88%国内企业已使用IoT;技术人才仍为最大需求;三分之一企业死于构想阶段

超 60 万 GPS 定位服务被曝漏洞,用户信息或将暴露!

2亿日活,日均千万级视频上传,快手推荐系统如何应对技术挑战?

Docker容器化部署Python应用

☞给面试官讲明白:一致性Hash的原理和实践

预警,CSW的50万枚尘封BTC即将重返市场?

☞她说:行!没事别嫁程序员!

640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

640?wx_fmt=png

你点的每个“在看”,我都认真当成了喜欢

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CSDN资讯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值