在 Git 中仅提交文件的一部分

当我在 Git 中更改文件时,如何仅提交某些更改?

例如,如何在文件中更改的 30 行中仅提交 15 行?

答案

您可以使用git add --patch <filename> (或简称-p ),并且 git 会开始将您的文件分解为它认为合理的 “大头”(文件的一部分)。然后它将提示您以下问题:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

这是每个选项的说明:

  • y暂存此块以进行下一次提交
  • n不要为下一次提交暂存此块
  • q退出;不要上演这个大块头或其他任何大块头
  • 这个大块阶段,以后所有大块都在文件中
  • d不要暂存此块或文件中的任何以后的块
  • g选择一个大块头去
  • /搜索与给定正则表达式匹配的块
  • j尚未确定此块,请参阅下一个未确定的块
  • J不确定这个大块,请看下一个大块
  • k尚未确定该大块,请参阅先前未确定的大块
  • K尚未确定此大块,请参阅先前的大块
  • s将当前块拆分为较小的块
  • e手动编辑当前大块
  • 打印大块帮助

如果文件不在存储库中,则可以先执行git add -N <filename> 。之后,您可以继续使用git add -p <filename>

之后,您可以使用:

  • git diff --staged检查您是否已进行正确的更改
  • git reset -p取消误添加大块头
  • git commit -v在编辑提交消息时查看您的提交。

注意,这与git format-patch命令大不相同,后者的目的是将提交数据解析为.patch文件。

未来参考: Git 工具 - 交互式登台

您可以使用git add --interactivegit add -p < <em>file</em> > ,然后使用git commit不是 git commit -a );请参阅git-add联机帮助页中的 “ 交互” 模式 ,或直接按照说明进行操作。

Modern Git 还具有git commit --interactive (和git commit --patch ,这是交互式提交中 patch 选项的快捷方式)。

如果您更喜欢通过 GUI 进行操作,则可以使用git-gui 。您可以简单地标记要包含在提交中的块。我个人发现它比使用git add -i更容易。其他 git GUI,例如 QGit 或 GitX,也可能具有此功能。

git gui在 diff 视图下提供了此功能。只需右键单击您感兴趣的行,您将看到 “暂存此行以提交” 菜单项。

我相信git add -e myfile是最简单的方法(至少是我的喜好),因为它只是打开了一个文本编辑器,并让您选择要git add -e myfile行和不需要的行。关于编辑命令:

添加的内容:

添加的内容以 “+” 开头的行表示。您可以通过删除它们来防止暂存任何附加行。

删除的内容:

删除的内容以 “-” 开头的行表示。您可以通过将 “-” 转换为 “”(空格)来防止分段删除它们。

修改内容:

修改后的内容由 “-” 行(删除旧内容)和 “+” 行(添加替换内容)表示。您可以通过将 “-” 行转换为 “” 并删除 “ +” 行来防止进行修改。请注意,仅修改一对中的一半可能会给索引带来混乱的变化。

关于git add每一个细节都可以在git --help add

如果您使用的是 vim,则可以尝试使用名为fugitive的出色插件。

您可以使用:Gdiff工作副本和索引之间文件的差异,然后使用经典的 vim diff 命令(例如dp在索引中添加行或块。将修改保存到索引中,然后使用:Gcommit提交, :Gcommit完成。

此处有非常好的入门级截屏视频(请参见第 2 部分 )。

我强烈建议使用 Atlassian 的SourceTree 。 (它是免费的。)这使它变得微不足道。您可以快速,轻松地暂存单个代码块或单个代码行。

在此处输入图片说明

值得注意的是,要对新文件使用git add --patch ,首先需要使用git add --intent-to-add将文件添加到索引:

git add -N file
git add -p file

当我进行了很多更改时,最终将根据更改创建一些提交,因此我想在暂存之前临时保存起点。

像这样:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

Whymarrh 的答案是我通常要做的,除了有时会有很多变化之外,我可以告诉我在上演事情时可能会犯错,而且我希望我可以回到第二阶段。

如果您使用 emacs,请看一下Magit ,它为 emacs 提供了 git 接口。它很好地支持暂存块 (文件的一部分)。

自 v2018.1 起,Intellij IDEA (我猜该系列的所有其他产品)都内置了对部分提交的支持

在此处输入图片说明