为什么?还有怎样才能保持你的 Git 提交历史清晰?

翻译 Insua ⋅ 于 3周前 ⋅ 1395 阅读 ⋅ 原文地址

站点的翻译文章创建时,您将第一时间收到通知。

这是一篇协同翻译的文章,目前翻译进度为 80%,你可以点击『我来翻译』按钮来 参与翻译

file
提交是 Git 仓库的重要组成部分之一,不仅于此,提交信息  贯穿于 Git 仓库的整个生命周期。随着项目/仓库的发展(新特性的增加、Bugs 的修复、架构的重构),提交信息可以让我们看到改了什么地方以及是如何改动的。因此,这些信息以一种简短、精确的方式反映着潜在的变化是非常重要的。

Explorer 翻译于 3周前

为什么有意义的提交历史很重要

Git 提交消息就像是你在你接触过的代码上面留下的指纹。任何你今天提交的代码,一年以后当你看到这段代码的变化时,你将感谢自己当时留下的清晰、有意义的提交信息,同时它还将使你的开发变得更为容易。当提交被基于上下文独立时,由某个提交引入的 Bug 将会更快被找到,并且更容易恢复到导致错误提交前的代码。

当你工作在一个大的项目中时,我们经常更新、新增或者移动文件。确保在这种情况下维持提交消息将很棘手,尤其是在开发周期跨越数天,数周甚至数月的情况下。因此,为了简化维护简洁提交历史记录的工作,这篇文章将使用开发人员在处理 Git 仓库时可能遇到的一些常见情况。

在我们深入讨论之前让我们快速的了解一下,在我们假设的 Ruby 应用程序中,典型的开发工作流是什么样子的。

注意: 这篇文章假定您了解基本的 Git 知识 、分支的工作方式、如何在阶段中添加未提交的分支更改以及如何提交更改。如果你不了解这些流程, 我们的文档 是一个很好的起点。

Explorer 翻译于 2周前

日常开发中的一天

现在,我们正在开发一个小型的 Ruby on Rails 项目。我们需要在首页添加一个导航视图,这涉及到更新和添加几个文件。下面是整个流程的逐步细分:

  • 你首先从更新某个文件开始来开发新功能;我们叫它为application_controller.rb
  • 这个功能也需要你更新一个视图文件:index.html.haml
  • 你添加了一个局部视图,它会在首页中用到:_navigation.html.haml
  • 页面样式也需要更新,让它作用到我们的视图上:styles.css.scss
  • 新功能已经准备好所有期望的修改,该更新测试文件了;要更新的文件如下:
    • application_controller_spec.rb
    • navigation_spec.rb
  • 测试文件更新完毕并如期通过,现在是时候提交所有更改了!

因为所有的文件分属于架构的不同区域,所以我们对这些更改彼此隔离进行提交,确保每次提交代表一个特定的上下文,并按顺序提交。我通常喜欢从后端 -> 前段的顺序。首先提交大多数以后端为中心的更改,接着是中间层,最后是在提交列表中以前端为中心的更改。

  1. application_controller.rb & application_controller_spec.rbAdd routes for navigation
  2. _navigation.html.haml & navigation_spec.rbPage Navigation View
  3. index.html.hamlRender navigation partial
  4. styles.css.scssAdd styles for navigation

现在我们已经提交了更改,我们使用分支来创建 merge 请求。一旦创建了 merge 请求,通常会在更改合并进 master分支之前由原仓库的拥有者进行审核。现在我们来了解一下,在代码审核期间我们可能会面临的不同情况。

mingc 翻译于 2周前

情况1:我需要修改最近的提交

想象一下,审阅者查看了styles.css.scss文件并建议进行更改。在这种情形下,进行更改非常简单,因为对样式的更改是你分支上 最近一次 提交的一部分。下面是我们怎样处理这次更改的步骤:

  • 你可以直接在你的分支上对styles.css.scss文件做必要的更改。
  • 一旦你完成了这些更改,请将这些改变添加到暂存区;运行git add styles.css.scss
  • 当这些改变被暂存之后,我们需要将这些更改 添加 到上次的提交中;运行 git commit --amend
    • 命令分解:在这里,我们要求git commit命令 修改 暂存区中的最近一次提交。
  • 这将会用你已定义的 Git 文本编辑器打开最近一次提交,并且提交消息是 Add styles for navigation
  • 因为我们只更新了 CSS 声明,所以无需修改提交消息。此时,你只需要保存并退出 Git 为你打开的文本编辑器,所有的更改将会反映在本次提交中。

由于你修改了现有的提交,所以必须使用git push --force-with-lease <remote_name> <branch_name>将这些更改 强制推送 到你的远程仓库。这个命令将会使用我们在本次仓库更新后的提交,覆盖远程仓库上消息为Add styles for navigation的那次提交。

在强制推送分支时需要注意的一件事是,如果你和其他同事工作于同一分支,当其他人尝试向一个刚被强制推送过的远程分支正常推送他们的更改时,可能遇到一些麻烦。所以,请明智地使用强制推送。你可以在 这里 了解有关 Git 强制推送的更多选项。

mingc 翻译于 2周前

情况 2:我需要更正一个特定的提交

在之前的情况下,由于我们只能修改最后一次提交,所以这种修复非常简单,但是想象一下,如果审稿人建议改变_navigation.html.haml。 在这种情况下,因为它是第二次从顶部提交,所以要想改变它不会像第一种情况那样直接。让我们还是来看看如何处理这个问题吧:

每当在分支中进行提交时,它就被唯一的SHA1哈希字符串标识。把它看作是一个唯一的ID,它将一个提交与另一个提交分开。通过运行git log,您可以查看分支中的所有提交以及它们的SHA1哈希。通过它,你会看到一个看起来有点类似下面这样的输出,其中最近的提交在顶部;

commit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD -> add-page-navigation)
Author: Kushal Pandya <kushal@gitlab.com>
Date: Wed May 2 15:24:02 2018 +0530

    Add styles for navigation

commit c22a3fa0c5cdc175f2b8232b9704079d27c619d0
Author: Kushal Pandya <kushal@gitlab.com>
Date: Wed May 2 08:42:52 2018 +0000

    Render navigation partial

commit 4155df1cdc7be01c98b0773497ff65c22ba1549f
Author: Kushal Pandya <kushal@gitlab.com>
Date: Wed May 2 08:42:51 2018 +0000

    Page Navigation View

commit 8d74af102941aa0b51e1a35b8ad731284e4b5a20
Author: Kushal Pandya <kushal@gitlab.com>
Date: Wed May 2 08:12:20 2018 +0000

    Add routes for navigation

这就是 Git ReBase 命令发挥作用的地方。每当我们希望编辑 git ReBase 的特定提交时,我们需要先将我们的分支重新定位为在我们希望编辑的提交之前,将头移到右边。在我们用例中,我们需要更改读取的提交  Page Navigation View

file

anzichen 翻译于 2周前

这里请注意,正确的提交哈希是我们想要修改提交的前一个提交哈希;拷贝那个哈希,然后执行下面的步骤:

  • 变基(rebase)分支,移动到目标提交的前一次提交;运行git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
    • 命令分解:这里我们运行rebase命令的 交互 模式,并提供了要变基的提交哈希。
  • 这将在 Git 交互模式运行 rebase 命令,并打开你的文本编辑器,里面显示了正在变基的提交(8d74af)之后 的所有提交。它看起来就像这样:
pick 4155df1cdc7 Page Navigation View
pick c22a3fa0c5c Render navigation partial
pick aa0a35a867e Add styles for navigation

# 在 8d74af10294 上变基 8d74af10294..aa0a35a867e 范围(3次提交)
#
# 命令:
# p, pick = 保留本次提交
# r, reword = 保留本次提交,但要修改提交消息
# e, edit = 保留本次提交,但暂停下来进行修改(不只修改提交消息)
# s, squash = 保留本次提交,但合并到前一次提交
# f, fixup = 与“squash”类似,但丢弃本次提交消息
# x, exec = 运行 shell 命令(本行的剩余内容)
# d, drop = 删除本次提交
#
# 这些行可以重排顺序,并自顶向底依次执行。
#
# 如果你删除一行,那次提交将会丢失。
#
# 如果你删除所有行,本次变基(rebase)将会中止。
#
# 注意空提交已注释掉。

注意每个提交前面都有一个单词pick,下面的注释是我们可能用到的关键字。因为我们想要 编辑 某此提交(4155df),所以需要把pick 4155df1cdc7 Page Navigation View改成edit 4155df1cdc7 Page Navigation View。保存修改,然后退出编辑器。

现在你的分支就重置到了所做的修改包含_navigation.html.haml的时刻。打开文件根据审核反馈执行需要的修改。一旦修改完毕,通过运行git add _navigation.html.haml命令进行暂存。

既然我们暂存了这些改变,现在是时候把 HEAD 分支移回我们的原始提交了(包含我们添加的最新修改),运行git rebase --continue,这将会在终端打开你的默认编辑器然后显示在变基(rebase)期间的提交消息;Page Navigation View。如果希望的话,你可以改变这个提交消息,但是我们现在让它保持现状,保存并退出编辑器。此刻,Git 会重新播放你所编辑的提交之后的所有提交,并且现在的HEAD分支回溯到了我们原始的顶部提交。

由于我们再次修改了远程仓库中已存在的一次提交,所以需要使用git push --force-with-lease <remote_name> <branch_name>强制推送分支。

mingc 翻译于 3天前

场景3:我需要添加、删除或者合并 commit

一个很常见的场景就是为了修复之前提交的内容,你已经 commit 了几次。现在我们来尽可能地减少 commit 的次数并把它们和原来的提交合并起来。

你需要做的就是就像你在其他场景一样启动交互式 rebase。

pick 4155df1cdc7 Page Navigation View
pick c22a3fa0c5c Render navigation partial
pick aa0a35a867e Add styles for navigation
pick 62e858a322 Fix a typo
pick 5c25eb48c8 Ops another fix
pick 7f0718efe9 Fix 2
pick f0ffc19ef7 Argh Another fix!

假设你现在想要把这些提交记录都合并到 c22a3fa0c5c Render navigation partial。你只需要做到:

  1. 将 fixes 向上移动直到它们位于你希望保留的最后的提交下面
  2. 把每一个 fix 的 pick 改为 squash 或者 fixup

注意: squash 保留了描述中的提交注释。 fixup 不会保留提交的注释而只保留原始注释。

你会得到这样的结果:

pick 4155df1cdc7 Page Navigation View
pick c22a3fa0c5c Render navigation partial
fixup 62e858a322 Fix a typo
fixup 5c25eb48c8 Ops another fix
fixup 7f0718efe9 Fix 2
fixup f0ffc19ef7 Argh Another fix!
pick aa0a35a867e Add styles for navigation

保存更改,退出编辑,你就完成了!这是产生的历史:

pick 4155df1cdc7 Page Navigation View
pick 96373c0bcf Render navigation partial
pick aa0a35a867e Add styles for navigation

和以前一样,你要做的就是 git push --force-with-lease <remote_name> <branch_name>,改变就生效了。

如果你想要完全地删除一个提交,把 squash 或者 fixup 换成 drop 或者干脆删掉那一行。

hiwynn 翻译于 5天前

Avoid conflicts

To avoid conflicts, make sure the commits you're moving up the timeline aren't touching the same files touched by the commits left after them.

pick 4155df1cdc7 Page Navigation View
pick c22a3fa0c5c Render navigation partial
fixup 62e858a322 Fix a typo                 # this changes styles.css
fixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg
fixup 7f0718efe9 Fix 2                      # this changes styles.css
fixup f0ffc19ef7 Argh Another fix!          # this changes styles.css
pick aa0a35a867e Add styles for navigation  # this changes index.html (no conflict)

Pro-tip: Quick fixups

If you know exactly which commit you want to fixup, when committing you don't have to waste brain cycles thinking of good temporary names for "Fix 1", "Fix 2", ..., "Fix 42".

Step 1: Meet --fixup

After you've staged the changes fixing whatever it is that needs fixing, just commit the changes like this:

git commit --fixup c22a3fa0c5c

(Note that this is the hash for the commit c22a3fa0c5c Render navigation partial)

This will generate this commit message: fixup! Render navigation partial.

Step 2: And the sidekick --autosquash

Easy interactive rebase. You can have git place the fixups automatically in the right place.

git rebase -i 4155df1cdc7 --autosquash

History will be shown like so:

pick 4155df1cdc7 Page Navigation View
pick c22a3fa0c5c Render navigation partial
fixup 62e858a322 Fix a typo
fixup 5c25eb48c8 Ops another fix
fixup 7f0718efe9 Fix 2
fixup f0ffc19ef7 Argh Another fix!
pick aa0a35a867e Add styles for navigation

Ready for you to just review and proceed.

If you're feeling adventurous you can do a non-interactive rebase git rebase --autosquash, but only if you like living dangerously, as you'll have no opportunity to review the squashes being made before they're applied.

Situation 4: My commit history doesn't make sense, I need a fresh start!

If we're working on a large feature, it is common to have several fixup and review-feedback changes that are being committed frequently. Instead of constantly rebasing the branch, we can leave the cleaning up of commits until the end of development.

This is where creating patch files is extremely handy. In fact, patch files were the primary way of sharing code over email while collaborating on large open source projects before Git-based services like GitLab were available to developers. Imagine you have one such branch (eg; add-page-navigation) where there are tons of commits that don't convey the underlying changes clearly. Here's how you can create a patch file for all the changes you made in this branch:

  • The first step to create the patch file is to make sure that your branch has all the changes present from master branch and has no conflicts with the same.
  • You can run git rebase master or git merge master while you're checked out in add-page-navigation branch to get all the changes from master on to your branch.
  • Now create the patch file; run git diff master add-page-navigation > ~/add_page_navigation.patch.
    • Command breakdown: Here we're using Git's diff feature, and asking for a diff between master branch and add-page-navigation branch, and redirecting the output (via > symbol) to a file named add_page_navigation.patch in our user home directory (typically ~/ in *nix operating systems).
  • You can specify any path you wish to keep this file in and the file name and extension could be anything you want.
  • Once the command is run and you don't see any errors, the patch file is generated.
  • Now checkout master branch; run git checkout master.
  • Delete the branch add-page-navigation from local repo; run git branch -D add-page-navigation. Remember, we already have changes of this branch in a created patch file.
  • Now create a new branch with the same name (while master is checked out); run git checkout -b add-page-navigation.
  • At this point, this is a fresh branch and doesn't have any of your changes.
  • Finally, apply your changes from the patch file; git apply ~/add_page_navigation.patch.
  • Here, all of your changes are applied in a branch and they will appear as uncommitted, as if all your modification where done, but none of the modifications were actually committed in the branch.
  • Now you can go ahead and commit individual files or files grouped by area of impact in the order you want with concise commit messages.

As with previous situations, we basically modified the whole branch, so it is time to force push!

总结

尽管我们已经介绍了使用 Git 进行日常工作流程中出现的大多数常见的情况,但重写 Git 历史是一个巨大的话题,并且当你在熟悉上述提示时,你可以在 Git 官方文档 学习围绕该主题的更高级概念。祝你愉快的学习 Git。

Ellison 翻译于 3周前

原文地址:https://about.gitlab.com/2018/06/07/keep...

译文地址:https://laravel-china.org/topics/13616/w...


本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

本帖已被设为精华帖!
回复数量: 0
    暂无评论~~
    您需要登陆以后才能留下评论!

    Composer 中国全量镜像

    Top 100 扩展包

    Lumen 中文文档

    Laravel 速查表

    Laravel 中文文档

    Laravel 项目开发规范

    Laravel 开发环境部署

    Elasticsearch-PHP 中文文档

    Lumen 中文文档

    GraphQL PHP 中文文档

    社区文档撰写指南

    TDD 构建 Laravel 论坛笔记

    PHP PSR 标准规范

    PHP 设计模式全集

    Dingo API 中文文档