在Git中仅提交文件的部分更改

当我在Git中对文件进行更改时,如何仅提交部分更改?

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

556158 次浏览

您可以使用:

git add --patch <filename>

或简称:

git add -p <filename>

Git会将您的文件分解为它认为合理的“块”(文件的一部分)。然后它会提示您以下问题:

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

以下是每个选项的描述:

  • y为下一次提交阶段这个大块头
  • n不要为下一次提交暂存这个大块
  • q退出;不要暂存此块或任何剩余的块
  • 一个在文件中暂存此块和所有稍后的块
  • d不要在文件中暂存此块或任何后续块
  • g选择一个大块去
  • //搜索与给定正则表达式匹配的大块
  • j离开这个大块未决定,看到下一个未决定的大块
  • J让这个大块头犹豫不决,看看下一个大块头
  • k保留此块未决定,参见上一个未决定的块
  • K离开这个大块头未定,见上一个大块头
  • 将当前块拆分为更小的块
  • e手动编辑当前块
    • 然后,您可以通过将+/-替换为#来手动编辑大块(感谢veksen
  • ?打印大块帮助

如果文件还没有在存储库中,您可以先执行git add -N <filename>。然后您可以继续执行git add -p <filename>

之后,您可以使用:

  • git diff --staged检查您是否执行了正确的更改
  • git reset -p取消错误添加的帅哥
  • git commit -v在编辑提交消息时查看您的提交。

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

未来参考:Git Tools-交互式暂存

gitgui在diff视图下提供此功能。只需右键单击您感兴趣的行,您应该会看到“将此行提交”菜单项。

您可以使用git add --interactivegit add -p <file>,然后使用git commit没有git commit -a);请参阅git-add手册中的交互模式,或者简单地按照说明进行操作。

现代Git也有git commit --interactive(和git commit --patch,这是交互式提交中补丁选项的快捷方式)。

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

如果您使用emacs,请查看Magit,它为emacs提供了一个git接口。它很好地支持登台大块头(文件的一部分)。

对于emacs也有gitsum

尝试了git add -p filename.x,但在mac上,我发现gitx(http://gitx.frim.nl/https://github.com/pieter/gitx)更容易完全提交我想要的行。

如果您使用的是vim,您可能想尝试名为逃犯的优秀插件。

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

非常好的介绍性截屏这里(参见esp.第2)。

当我有很多更改时,最终会从更改中创建一些提交,然后我想在暂存之前暂时保存我的起点。

像这样:

$ git stash -uSaved 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的回答是我通常做的,除了有时会有很多变化,我可以告诉我可能会在分期付款时犯错误,我想要一个承诺的状态,我可以依靠第二次传递。

就像jdsum sion的答案一样,你也可以隐藏你当前的工作,但然后使用像meld这样的扩散工具从存储中提取选定的更改。这样你甚至可以非常容易地手动编辑大块,这在git add -p时有点痛苦:

$ git stash -u$ git difftool -d -t meld stash$ git commit -a -m "some message"$ git stash pop

使用stash方法使您有机会在提交之前测试您的代码是否仍然有效。

如上面的一个答案所示,您可以使用git add--patchfilename.txt

或短格式git add-pfilename.txt

…但是对于已经在您的存储库中的文件,在s中直接在提交命令上使用--patch标志要好得多(如果您使用的是最新版本的git):git提交--patchfilename.txt

…或者,同样,短格式filename.txt

…然后使用提到的键(y/n等)来选择要包含在提交中的行。

我强烈建议使用艾特莱森的资源树。(它是免费的。)它使这变得简单。您可以快速轻松地准备单个大块代码或单个代码行。

输入图片描述

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

git add -N filegit add -p file

vim-gitgutter插件可以在不离开vim编辑器的情况下使用

:GitGutterStageHunk

除此之外,它还提供了其他很酷的功能,例如一些现代IDE中的diff符号列

如果只有大块的一部分应该上演维姆逃犯

:Gdiff

允许视觉范围选择然后:'<,'>diffput:'<,'>diffget阶段/恢复单个行更改。

使用TortoiseGit:

右键单击文件并使用Context Menu → Restore after commit。这将按原样创建文件的副本。然后您可以编辑文件,例如在TortoiseGitMerge中并撤消所有您不想提交的更改。保存这些更改后,您可以提交文件。

如果它在Windows平台上,在我看来git gui是一个很好的工具,可以从unstaged文件stage/commit几行

1.大块头:

  • unstagged Changes部分选择文件
  • 右键单击需要暂存的代码块
  • 选择Stage Hunk for commit

2.分行:

  • unstagged Changes部分选择文件
  • 选择要上演的台词
  • 右键单击并选择Stage Lines for commit

3.如果您想暂存完整的文件,除了几行:

  • unstagged Changes部分选择文件
  • Ctrl+T (Stage file to commit)
  • 选定的文件现在移动到Staged Changes部分
  • 选择要上演的台词/台词
  • 右键单击并选择UnStage Lines for commit

git-meld-index使用方法-引用网站:

git-meld-index运行meld——或任何其他git漫射工具(k的3,漫射等)——允许您交互式地阶段更改git索引(也称为git暂存区域)。

这类似于git add-p和git add--互动的功能。在某些情况下,meld比git add-p更容易/更快地使用。这是因为meld允许您,例如:

  • 查看更多上下文
  • 看到行内差异
  • 手动编辑并查看'live'diff更新(每次按键后更新)
  • 导航到更改,而不对您要跳过的每个更改说“n”

用法

在git存储库中,运行:

git meld-index

您将看到meld(或您配置的git扩散工具)弹出:

:从工作树复制的临时目录连续文件

:包含索引内容的临时目录。这还包括尚未在索引中但在工作副本中被修改或未跟踪的文件——在这种情况下,您将看到来自HEAD的文件内容。

编辑索引(右手边)直到满意。记得在需要时保存。

完成后,关闭meld,git-meld-index将更新索引以匹配刚刚编辑的meld右侧临时目录的内容。

对于那些使用git扩展的人:

在提交窗口中,选择要部分提交的文件,然后在右窗格中选择要提交的文本,然后右键单击该选择并从上下文菜单中选择“阶段选定行”。

git-cola是一个很棒的GUI,也内置了这个功能。只需选择要暂存的行并按S。如果没有选择,则暂存完整的大块。

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

添加内容:

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

删除内容:

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

修改内容:

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

关于git add的所有细节都可以在git --help add上找到

IntelliJ IDEA(以及该系列的所有其他产品)自v2018.1以来内置了对部分提交的支持。

输入图片描述

对于Atom用户,包github包括git gui样式的交互式暂存。有关快捷方式,请参阅包的留档

使用Atom允许使用具有深色背景的主题(默认情况下,#0具有白色背景)。

添加到前面的答案,如果您更喜欢使用命令行,输入git add -e myfile可以让您选择逐行选择您想要提交的内容,因为此命令将打开一个具有差异的编辑器,如下所示:

在此处输入图片描述

如你所知,以+开头的行是添加,以-开头的行是删除。所以:

  • 为了不进行添加,只需删除该行。
  • 为了不进行删除,只需将-替换为空间

这就是git add -h关于以这种方式添加文件(修补文件)的说明:

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

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

修改内容:修改后的内容由“-”行表示(删除旧的内容)后跟“+”行(添加替换内容)。您可以通过将“-”行转换为"",并删除"+"行。注意,只修改一半的对可能会引入令人困惑的索引更改。

注意:不要更改文件的内容,这不是一个好地方。只需更改删除或添加行的运算符。

自从这个问题被问到已经有10年了。我希望这个答案对某人有用。正如答案这里中提到的,GUI不是一个选项,Andrej ShaDura的git记录工具帮助带来了一个交互式窗口,我们可以在其中选择要提交的行。

设置扩展如下:

git clone https://github.com/andrewshadura/git-crecordcd git-crecord./setup.py installln -s $PWD/git-crecord ~/.local/bin/git-crecord

cd到您的git repo并按如下方式调用它:

git crecord

这将打开一个交互式界面,可按如下所示使用。按下以下键将执行某些操作:

f       hunk toggle fold (arrow keys can also be used)space   toggle hunk selectiona       toggle commit or amendc       confirm and open commit window

显示示例用法的屏幕广播示例

如果您碰巧使用VS Code,那么您很幸运。选择要暂存的范围,然后使用Git: Stage Selected Ranges暂存它们,并根据需要提交。

我录了一个gif来证明我的意思:

输入图片描述

您可以使用Eclipse IDE,每个修改后的本地文件都可以与分阶段区域进行比较,并且在这个并排差异视图中,您可以自由选择要从本地复制到分阶段区域的大块,或者相反,从分阶段区域回滚本地更改。

但是还有更多:),所有图形化的git客户端也做了这个大块暂存(git add-p),但我知道没有一个可以做到这一点:直接在暂存区域编辑,所以同一行或同一大块上的几个更改可以被更精细地拾取(甚至写/删除/更新本地不存在的东西),就像在补丁级别工作的“git add-e”,但没有破坏补丁内容的风险。此外,由于它是在diff视图中使用常规文本编辑器,因此您可以使用语法颜色来帮助,并且可以执行文本替换操作(更改所有缩进类型,在许多地方重命名局部变量,…)以开始单独提交一些重新格式化/重构,然后再提交您的“真正”更改,但不将所有文件更改嵌入同一提交中。

当然,Eclipse更面向Java,但由于其强大的git暂存编辑器,它也可以用于其他语言。有一个基于Eclipse的免费产品仅专注于git操作,称为GitEye:https://www.collab.net/downloads/giteye,但似乎没有更好地使用基本的Eclipse发行版,如:https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-java-developers

编辑:由于IntelliJ 2020.3允许使用真实的git索引,它现在能够像Eclipse一样直接编辑分阶段区域

我想把lazygit添加到工具列表中。这是一个很好的命令行GUI(即,即使不允许X转发也可以通过ssh工作)。它具有广泛的功能(例如,选择要提交的行,交互式rebase),有用的着色,并且使用起来相对简单。可以以多种方式安装(go,conda,包管理器…)。仍在积极开发/维护。

2018年答案的评论

很遗憾Visual Studio没有这个选项。
大约10年前,替代源代码控制系统Mercurial在Visual Studio中支持此功能。自从我使用Git以来,我真的很想念它。

现在(2022年8月)支持:

Git行暂存发布!

我们很高兴地宣布在Visual Studio 2022中发布Line-stage支持。

Line-staging-交互式暂存,使您能够将更改的代码行拆分到不同的提交中。
行暂存也可以用于在提交更改之前审查更改。通过暂存标记更改的行或代码段,并在完成后提交暂存更改。

通过将Visual Studio 2022更新到版本17.3或更高版本来开始使用Line-stage。

VS 17.03交互式暂存--https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2022/08/Line-stagingM.mp4

阅读我们的线路暂存留档以了解有关如何使用和自定义此功能的更多信息。

在所有这些工具中,我最喜欢叉子(虽然不是免费的)!

与其他的相比,它是非常时尚和优雅的使用,点击按钮旁边你的鼠标将做大块或行分期。

另一个选项是GitKraken,有趣但更复杂和强大!