Git 组织:更好的 Git 流程

2025-05-26

Git 组织:更好的 Git 流程

想象一下:你被派去调查一起生产事故,经过一番调查后,你找到了包含破坏性代码的提交。你决定撤销这项更改:

$ git revert 1a2b3c
Enter fullscreen mode Exit fullscreen mode

不幸的是,这样做会引入一个新的 bug!原来,在那个旧的“损坏”提交中隐藏着应用程序其他部分依赖的一些代码,当你还原这些代码行时,网站又一次陷入了崩溃状态。🙃 哎呀!

如何避免这种情况?要回答这个问题,我们首先需要研究这些类型的提交是如何产生的。

常见的 Git 流程

让我们看一下构建新功能时的常见 git 流程:

  1. 从 创建一个新分支main
  2. 创建提交以保存您的工作并修复您在过程中发现的错误。
  3. 当功能完成后,发出拉取请求。
  4. mainPR 获得批准后,合并分支。

您可能觉得这个流程很熟悉,这没关系。我们很多人都是这样学习使用 Git 的。然而,这种方法存在两个问题。第一个问题我们已经讨论过了,那就是,如果您只是简单地进行提交,某些提交可能包含不完整的工作。这使得恢复操作相当危险。

第二个问题是,它会让审查拉取请求变得非常繁琐。例如,如果你被要求审查一个最近的 PR,其中作者声明除了添加新功能外,他们还修复了一个不相关的错误。该 PR 包含数十个文件的更改。单独查看每个提交并不能确定哪些更改与错误修复有关,哪些更改与新功能有关。此外,你还会注意到一些更改似乎与 PR 描述中的任何内容都无关。显然,这不会是一个快速的审查。

现在,虽然每次提交都只与一个变更紧密相关固然很好,但在开发过程中,这却是一项艰巨的任务。修改和重写只是流程的一部分。我们的工作很少如此线性,我们的 git 提交也往往反映了这一点。

那么,我们如何才能保证我们的 git 历史记录整洁、易于查看,同时又能接受开发过程中一些无关紧要的性质呢?通过稍微修改这个基本的 git 流程,我们可以创建一个更好的流程来实现这一点。

改进的 Git Flow

以下方法受我的同事 Dan Wendorf 启发,他的 git 流程通常围绕一个核心原则:先做工作,后清理提交。这种流程的好处在于,它将工程 工作提交的编写分离开来。最终,我们将得到一系列按逻辑分组的提交,每个提交都与代码中的一个主要更改相关,从而清理我们的 git 历史记录,并为更快的 PR 审核铺平道路。

我们可以将其分为以下三个步骤。

步骤 1:进行更改

第一步与之前并无太大区别。首先创建一个新分支,然后开始进行修改。暂时不必太在意编写描述性提交信息,因为这些信息不会包含在最终的 PR 中。现在,一个简单的“工作进行中”或“WIP”信息就可以了,或者一些能帮助你记住提交内容的信息,例如“WIP:开始构建新模型”。这些提交的目的是确保你不会丢失工作成果,并在工作过程中提供一些通用的指导。

$ git checkout -b my-feature-branch

...make changes...

$ git commit -m"WIP"

...make more changes...

$ git commit -m"WIP"

...make even more changes...

$ git commit -m"WIP"
Enter fullscreen mode Exit fullscreen mode

在此步骤中,可以保留代码库的缺陷状态,或者提交一些尚未完成的功能。这些功能稍后都会被清理。

第 2 步:重置

完成更改后,就该准备执行“git clean up”了。为此,我们将运行以下命令:

$ git reset origin/main
Enter fullscreen mode Exit fullscreen mode

如果不添加任何额外参数,git reset则不会更改工作树,因此您的代码不会更改——您所做的所有工作仍会保留在那里。但由于您已重置为较旧的提交,因此git status将显示自开始构建功能以来所做的所有更改。看起来您完成了所有工作,但之前从未进行过任何“WIP”提交。

$ git reset origin/main
Unstaged changes after reset:
M       src/components/Footer/Footer.tsx
M       src/components/Nav/Nav.css
M       src/components/Nav/Nav.tsx
M       src/components/Posts/Post.tsx
M       src/components/Posts/PostList.tsx

$ git status
On branch feature-branch
Your branch is behind 'origin/feature-branch' by 3 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/components/Footer/Footer.tsx
        modified:   src/components/Nav/Nav.css
        modified:   src/components/Nav/Nav.tsx
        modified:   src/components/Posts/Post.tsx
        modified:   src/components/Posts/PostList.tsx
Enter fullscreen mode Exit fullscreen mode

如果你在这里遇到问题,别担心——你随时可以恢复你最初的提交!你所做的每个提交都会保留在你的.git文件夹中,即使过了一段时间reset。即使它们看起来像是消失了,但它们仍然在那里,隐藏着。

如果您想回到某个未发生任何损坏的提交,git reflog它会显示您在本地仓库中引用的每个提交的时间线,即使跨分支也是如此。运行git reflog找到您想要返回的提交,然后运行git reset <commit-sha>​​。此命令会将当前分支的 HEAD 指向该提交,然后您就可以重新开始工作了!

从这里开始,我们准备开始做出新的承诺。

步骤 3:创建新的、逻辑分组的提交

现在,查看所有已更改的文件。有哪些文件可以按逻辑分组?例如,所有与特定模型相关的依赖项更新或变更。文件分组没有“正确”的方法,因此请自行判断。将这些文件添加到暂存区,并提交描述这些更改的提交。

$ git add src/components/Nav/Nav.css
$ git add src/components/Nav/Nav.tsx
$ git commit -m"Added new styles to navigation"

$ git add src/components/Posts/Post.tsx
$ git add src/components/Posts/PostList.tsx
$ git commit -m"Updated author images on posts"

$ git add src/components/Footer/Footer.tsx
$ git commit -m"Fixed responsive bug in footer"
Enter fullscreen mode Exit fullscreen mode

如果您没有更改很多文件,则可能不需要多次提交,但我们通常可以通过将更改拆分为人类可读、易于遵循的提交,使我们的拉取请求更容易审查。

如果同一个文件包含多个需要单独分组的更改,该怎么办?可以使用( 或)暂存文件的部分内容。一些代码编辑器还提供了暂存一系列更改(而非整个文件)的方法。git add --patchgit add -p

在此步骤中,请注意不要让代码库处于损坏状态。记住,我们清理提交的一个重要原因是,如果我们想要还原更改,就不会出现任何问题。在进行其中一个新提交后,您可以查看git stash其余未暂存的更改,并测试一切是否仍然正常工作。如果您意识到应该在该提交中包含另一个文件,您可以git stash pop恢复其他更改和git add丢失的文件,然后执行git commit --amend。此命令将用具有相同描述的新提交替换上一个提交,其中包含旧提交和您刚刚所做的更改。

最终结果

将工作拆分成逻辑分组的提交后,您就可以创建拉取请求了!最终结果是一组更改,您的同事可以以可管理的块为单位,一次审核一个提交。

PR 中逻辑组织的提交

这种 git 流的好处是,它允许典型开发的流动性,同时还提供一些维护存储库历史记录所急需的顺序。

文章来源:https://dev.to/render/git-organized-a-better-git-flow-56go
PREV
如何以 10 倍速度构建前端应用程序
NEXT
创建一个令人惊叹的 Github 个人资料💫(通过动态列出您最近的博客文章)