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

作者 | Manuel Sidler

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

出品 | CSDN(ID:CSDNnews)

以下为译文:

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

要事第一

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

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

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

git commit -amend

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

git commit –amend -m“new message”

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

git commit --amend --no-edit

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

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场景。

场景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, withgit commit --amend Once you are satisfied with your changes, rungit rebase --continue

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

git commit --amend

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

git rebase –continue

场景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

场景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

多整洁!

场景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)

场景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.

场景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历史记录整洁的重要性。假设我们将不同的特性放入一个提交中,或者将一个特性拆分为多个(无意义的)提交,那么还原要复杂得多。

当事情出现问题时

在重写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 云平台连接服务的技术框架实现细节、物联网协议应用和多协议,多网络的落地实践以及连接服务未来的演进方向。

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

 热 文 推 荐 

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

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

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

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

☞Docker容器化部署Python应用

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

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

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

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

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

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

  1. GIT(一):版本控制、git历史、git基本概念、git安装配置、git版本管理(本地和远程)、git分支管理

    目录 一.版本控制 1.1 版本控制概念 1.2 版本控制软件分类 1.2.1 集中式版本控制 1.2.2 分布式版本控制 二.git历史 三.GIT基本概念 3.1 GIT原理 3.1.1 GIT基 ...

  2. 从git中永久物理删除私密文件(改写git历史)

    第一步:切换到git本地库的最上一级 第二步:递归重写git历史 # git filter-branch --tree-filter 'rm -f admin/test.sh ' --tag-name ...

  3. 修改git历史提交的commit信息

    本文是基于idea的操作,亲测可用 前言: 很多公司都会自定义 Git - 使用强制策略,那么他的commit信息就会有固定的格式,一旦不是这个格式,就会出现push失败 但是push失败,很多也只在 ...

  4. 使用bfg快速清理git历史大文件

    文章目录 使用bfg快速清理git历史大文件 步骤 脚本 清理服务器 使用bfg快速清理git历史大文件 之前写过一篇的,使用的git命令清理的大文件,但是我3G多的git,.git文件夹里面的pac ...

  5. 如何清除Git历史变更记录

    以前公司的一个项目代码,从2014年一直存活到了2021年,目前应该还在被使用.整个代码将近2G,git文件极大,其中很大的一个原因是代码里存放过apk文件.如此大的项目,导致下载.发布很困难. 最初 ...

  6. eclipse查看代码git历史_Eclipse中GIT历史版本比较和回退

    Eclipse中GIT历史版本比较和回退 我们开发的时候,经常会遇到业务变化或者代码实现逻辑改变,有时候需要参考或者回退历史版本,我们看看eclispe里如何操作? 查看主分支历史版本 右击代码文件- ...

  7. git历史提交信息和提交时间修改

    git历史提交信息和提交时间修改 修改历史提交信息 修改历史提交时间 修改历史提交信息 执行:git rebase -i HEAD~10,这里的含义是修改最近10条数据 执行后会进入到修改界面,将要修 ...

  8. git 历史操作日志_Git - 查看提交历史

    查看提交历史 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史. 完成这个任务最简单而又有效的工具是 git log 命令. 我们使用一个非常简单的 "simplegit& ...

  9. git:历史版本回滚、重新回到最新版本及取消修改内容

    重新检出历史版本 场景:需要回到之前的版本,修改参数执行一下代码 查看历史版本号 git log -10 #查看最近10次commit的记录 检出历史版本 git checkout <版本号&g ...

最新文章

  1. C ++基本输入/输出
  2. 网站开发流程以及HTML5简介(三)
  3. 网站SEO优化技巧的“减法运算”
  4. 查看命令为内置命令还是外部命令
  5. Lambda省略格式Lambda使用前提
  6. response 中OutputStream和PrintWriter区别
  7. 关于XtraGrid的CustomUnboundColumnData事件的触发条件
  8. 离线语法设置 科大讯飞_科大讯飞智能键盘K710评测 输入速度超级加倍
  9. 茅台酒是不是勾兑的?
  10. 超10000支团队参赛,阿里云首届云原生编程挑战赛完美收官
  11. 使用fastcgi_cache加速你的Nginx网站
  12. LaTeX数学符号汇总
  13. 学生用计算机中括号怎么打,大括号怎么打,教您word大括号怎么输入
  14. 免费好用的英语单词统计软件(带翻译功能)
  15. win10系统快速进入bios的设置方法
  16. segy和su文件格式说明
  17. 量化交易入门阶段——欧奈尔的CANSLIM模型(S 供需关系)
  18. MD5 加密安全吗?
  19. ata高级计算机系统,ATAOffice2010年高级解题步骤.pdf
  20. STM32寄存器编程思路 - 从51到stm32开发入门,真干货

热门文章

  1. GTK+ 3.5.18 发布,GUI 开发工具包
  2. Win32汇编---控件的超类化感想
  3. 将XML文件数据插入到数据库中
  4. 百度EasyDL-表格数据预测试用示例
  5. Python地理数据处理库GDAL调研记录
  6. 动画学习android,Android动画学习
  7. linux java解压文件怎么打开,linux下面的解压缩文件的命令
  8. 命令窗口ping oracle,Oracle中tnsping命令解析
  9. jetson nano 在opencv拉流的视频上显示中文汉字(含c++完整源码)
  10. Golang并发模式基础