题 在Git中只提交文件的一部分


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

例如,我怎样才能在文件中更改的30行中只提交15行?


2242
2017-07-06 02:25


起源




答案:


您可以使用 git add --patch <filename> (要么 -p 简而言之,git将开始将你的文件分解为它认为合理的“帅哥”(文件的一部分)。然后它会提示您这个问题:

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

以下是每个选项的说明:

  • ÿ 为下一次提交提供此块
  • ñ 不要为下次提交暂存这个大块
  • q 放弃;不要把这个大块头或任何剩下的帅哥分开
  • 一个 将这个大块头和所有后来的人都放在文件中
  • d 不要在文件中放置这个大块或任何后来的帅哥
  • G 选择一个大块去
  • / 搜索与给定正则表达式匹配的块
  • Ĵ 离开这个大块未定,看下一个未定的大块头
  • Ĵ 离开这个大块未定,看下一个大块头
  • ķ 离开这个大块未定,看到先前未定的大块头
  • ķ 离开这个大块未定,看看上一个大块头
  • 小号 将当前的大块头分成了较小的帅哥
  • Ë 手动编辑当前的大块头
  •  打印厚片帮助

如果文件尚未存储在存储库中,您可以先执行此操作 git add -N <filename>。之后你可以继续 git add -p <filename>

之后,您可以使用:
git diff --staged 检查您是否进行了正确的更改
git reset -p 不要错误地添加帅哥
git commit -v 在编辑提交消息时查看提交。

请注意,这与 git format-patch 命令,其目的是将提交数据解析为 .patch 文件。

参考未来: https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging


2939
2017-07-06 11:49



注意这可能是有用的 -p/--patch 是一个补丁动作的快捷方式 -i/--interactive 启动有用的命令 互动模式。 - tutuDajuju
>如果该文件已经上演,会发生什么?它只会显示未分级的更改。与...一样 git diff 确实。 - Eugen Konkov
如何手动编辑当前的块?我打字后我不知道该怎么办。 - Hunsu
按下后 e,您可以通过替换手动编辑块 + 要么 - 通过 # - veksen
不 s 不再存在了? - tam5


您可以使用 git add --interactive 要么 git add -p <文件>, 接着 git commit (  git commit -a);看到 互动模式 在 混帐相加 手册页,或只是按照说明。

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

如果您更喜欢从GUI进行,您可以使用 混帐贵。您只需标记要包含在提交中的块。我个人认为比使用更容易 git add -i。其他git GUI,如QGit或GitX,也可能具有此功能。


216
2017-07-06 02:41



有趣的是,windows.github.com支持部分文件提交,但似乎最近放弃了它。 - Juri
@Juri我认为对部分文件提交的支持又回来了。 - Ela782
@ Ela782哦..是的,你说得对。 Thx指出了这一点。 - Juri
@Juri欢迎你。我实际上从来没有注意到它曾经在那里 - 我上周看到它并且想“哦,这是一个多么神奇的新功能”! :-) - Ela782
现在windows.github.com重定向到重新命名的GitHub桌面,它比Git GUI更好,支持部分提交......但不支持提交签名。叹。 - hacksalot


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


115
2017-09-25 20:45



对于复杂的补丁,这对我来说通常是最快的方法。 - hochl
这是一种非常有效且直观的方式,可以以细粒度的方式向暂存区域添加更改。还可以选择多行,并添加该选择内的所有更改。 - jox


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

添加内容:

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

删除内容:

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

修改内容:

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

每一个细节 git add 可用 git --help add 


55
2018-02-23 10:37



如果对如何实际选择那些线(即要输入的实际命令)有明确的解释,这将更有用。我在文档中找不到一个。你能加一个参考吗? - Alex
对于那些不喜欢速记选项的人, -e 是 --edit。 - Kolyunya
@Alex由theFreedomBanana添加的参考引号来自编辑补丁中的部分 git --help add - Randall
这是唯一的答案(只需要git)解决了当你不能让帅哥变小的时候添加/删除行的问题 s 在交互式补丁模式下。 - cdosborn
抱歉,我不想创建新问题,但是在运行此命令时如何使用通配符?我尝试使用git add -e - ** / * Activity.java但它没有用。但是git diff - ** / * Activity.java有效。看起来-e选项在这种情况下需要特殊处理。 - ka3ak


如果你正在使用vim,你可能想尝试一下这个优秀的插件 逃亡

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

非常好的介绍性截屏视频 这里 (见尤其是 第2部分)。


41
2017-08-12 13:32



非常感谢你的链接。完全一样,我需要的。特别 :diffget/:diffput 在可视模式下,我可以选择要重置/提交的特定行。所以,再次确定:vim很棒。 - goodniceweb


我强烈建议使用 SourceTree 来自Atlassian。 (它是免费的。)这使得这个微不足道。您可以快速轻松地分发各个代码或各行代码。

enter image description here


26
2017-12-05 17:29



我同意SourceTree是一个很好的工具,因为它可以提供比命令行更精细的控制。
@cupcake我认为相反,看到SourceTree可能使用那些命令行git可执行文件,本质上总是可以通过“命令行”执行相同(或更多)细粒度的操作。 - tutuDajuju
无论如何 细粒度 我强烈推荐的论点 SourceTree 作为分段帅哥和个人线条非常容易: i.imgur.com/85bNu4C.png - Michael Freeman
@tutuDajuju在这种情况下,我不确定这是真的。 SourceTree能够选择要分阶段的部分 逐行。你不需要整个大块头;你可以在一个大块中间分两条线。但我不知道它是如何实现的。 (目前,我正在尝试解决SourceTree无法为未跟踪文件分配特定行的问题。我在这里寻找解决方法,但发现git显然似乎没有提供逐行的能力完全没有。至少不是直截了当的。) - jpmc26
你可以用 --patch (正如其他答案建议的那样)和分裂大块直到你可以分段你想要的行。还有许多其他的包装和扩展提供了一个UI(通常以差异的形式),允许 apply来自选定行的补丁;比如内置 git gui 和 git-meld-index。只是说,源代码树不是那么好(以前的用户) - tutuDajuju


值得注意的是使用 git add --patch 为一个 新文件 您需要先将文件添加到索引中 git add --intent-to-add

git add -N file
git add -p file

20
2018-06-06 22:14





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

喜欢这个:

$ 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的答案就是我通常所做的,除非有时会有很多变化,我可以告诉我在分阶段时可能会犯错误,我想要一个承诺状态,我可以再次使用。


17
2017-07-08 07:00





如果您使用emacs,请查看 Magit,它为emacs提供了一个git接口。它支持 分享帅哥 (部分文件)相当不错。


12
2017-08-07 13:25



当我从M-x shell窗口运行它时,我经常会想要打开编辑器的git命令。 magit是否拦截了疯狂,并为此打开了一个新的缓冲区? (请不要使用background-emacs-daemon提示;无论如何,谢谢,但生命太短了)。 - user2066657
不,据我所知,它不会拦截这一点。但是不要只听我的话因为(1)我几乎没有在Emacs中使用shell窗口,(2)我通常使用emacsclient。话虽如此,如果是emacsclient 是 一个选项,至少可以防止打开emacs的附加窗口,并在我现有的Emacs窗口中打开“COMMIT_EDITMSG”缓冲区。 - Mark van Lent


就像jdsumsion的回答一样,你也可以隐藏你当前的工作,但是然后使用像meld这样的difftool从存储中提取选定的更改。这样你甚至可以很容易地手动编辑帅哥,这在进入时会有点痛苦 git add -p

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

使用stash方法可以在提交代码之前测试代码是否仍然有效。


7
2017-07-27 09:52



这很好用,但如果你使用 git commit --amend,看来你之后不能弹出藏匿,还是有办法做到这一点? - Mark