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

fre*_*ara 2629 git git-commit

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

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

clo*_*ead 3496

你可以使用git add --patch <filename>(或-p简称),git将开始将你的文件分解为它认为合理的"帅哥"(文件的一部分).然后它会提示您这个问题:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?
Run Code Online (Sandbox Code Playgroud)

以下是每个选项的说明:

  • y 为下一次提交提供此块
  • n 不要为下次提交暂存此块
  • q放弃; 不要把这个大块头或任何剩下的帅哥放在一边
  • a 将这个大块头和所有后来的人都放在文件中
  • 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工具 - 交互式分段

  • 注意`-p/ - patch`是`-i/ - interactive`命令中补丁操作的快捷方式可能是有用的,它启动了有用的[_Interactive mode_](http:// git-scm. COM /文档/混帐添加#_interactive_mode). (75认同)
  • 按下`e`后,您可以通过用`#`替换`+'或`-`来手动编辑Hunk (19认同)
  • >如果该文件已经上演,会发生什么?它只显示未分级的更改.和`git diff`一样. (4认同)
  • 如何手动编辑当前的大块?我打字后我不知道该怎么办. (3认同)
  • 嗯...当我执行 `git commit file` 时,它会提交所有内容,而不仅仅是我想要的特定更改(即使 `git diff --staged` 仅显示我想要的特定更改)**编辑:`git commit -p ` 会让你选择“大块头”并一次性提交;它只提交特定的更改** (2认同)
  • 恕我直言,拉法的评论应该纳入答案中。OP 的问题是如何提交更改,而不是暂存更改。至少需要提及`git commit -p`。 (2认同)

Jak*_*ski 243

您可以使用git add --interactive或,然后(); 看到交互模式的git-ADD手册页,或只需按照说明进行操作.git add -p <file>git commit git commit -a

Modern Git也有git commit --interactive(并且git commit --patch,它是交互式提交中补丁选项的快捷方式).

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


Ion*_*tan 138

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

  • 对于复杂的补丁,这对我来说通常是最快的方法. (11认同)
  • 这是一种非常有效且直观的方式,可以以细粒度的方式向暂存区域添加更改.还可以选择多行,并添加该选择内的所有更改. (5认同)
  • 请注意,这不是“gitk”,但它包含在 Windows 版 Git Bash 中;您应该有一个开始菜单条目,或者可以使用命令“git gui”启动它。还有“stage this hunk”,它可能比“stage this line”更有用。可能是新答案,因为这个答案是 10 年前创建的。 (3认同)

the*_*ana 72

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

添加内容:

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

删除内容:

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

修改内容:

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

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

  • 如果在某处如何实际选择那些线(即要输入的实际命令)有明确的解释,这将更有用.我在文档中找不到一个.你能加一个参考吗? (7认同)
  • 了解此命令(`git add -e`)*不会*更改磁盘上的文件内容可能会有所帮助。它只是将部分更改从未暂存到已暂存(索引)。 (6认同)
  • 这是唯一的答案(只需要git),解决了在交互式补丁模式下无法使用`s`缩小时,可以解决添加/删除行的问题. (5认同)
  • 对于那些不喜欢速记选项的人来说,`-e`是`--edit`. (3认同)
  • @Alex由theFreedomBanana添加的参考引号来自`git --help add`中的EDITING PATCHES部分 (2认同)

Fra*_*ois 42

如果你正在使用vim,你可能想尝试一个名为fugitive的优秀插件.

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

这里有非常好的介绍性截屏(参见第2部分).


小智 28

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

在此输入图像描述

  • @cupcake我认为相反,看到SourceTree可能使用那些命令行git可执行文件,本质上总是可以通过"命令行"执行相同(或更多)细粒度的操作. (16认同)
  • @Sun 您可以单击第 50 行,然后按住 Shift 键并单击第 100 行,然后进入舞台。您可以轻松地在 Sourcetree 中暂存第 50-100 行:) (5认同)
  • 我同意 SourceTree 是实现此目的的一个很好的工具,因为它为您提供了比通过命令行实现的更细粒度的控制。 (3认同)
  • 无论*细粒度的*论点我都强烈推荐**SourceTree**作为分段帅哥和个人系列非常简单:http://i.imgur.com/85bNu4C.png (2认同)

use*_*062 24

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

git add -N file
git add -p file
Run Code Online (Sandbox Code Playgroud)


jds*_*ion 22

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

像这样:

$ 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
Run Code Online (Sandbox Code Playgroud)

Whymarrh的答案就是我通常所做的,除非有时候会有很多变化,我可以告诉我在进行事情时可能会犯错误,我想要一个忠诚的状态,我可以再次使用.


San*_*eva 13

首先,我们可以看看有哪些变化。

git diff <file>
Run Code Online (Sandbox Code Playgroud)

如果它显示在不同的块中,我们可以使用

git add -p <file>
Run Code Online (Sandbox Code Playgroud)

通过接受或拒绝更改(y 或n)。

在此输入图像描述

如果没有,我们仍然可以借助 VS Code 来完成

在此输入图像描述


Mar*_*ent 12

如果您使用emacs,请查看Magit,它为emacs提供了一个git界面.它支持很好地分阶段(文件的一部分).


Hol*_*ndl 10

Intellij IDEA(我猜这个系列的所有其他产品)自v2018.1以来内置了对部分提交的支持

在此输入图像描述

  • @amiabl 你不能(从 v2020.1 开始)。由 https://youtrack.jetbrains.com/issue/IDEA-186988 跟踪 (3认同)

der*_*och 8

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

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop
Run Code Online (Sandbox Code Playgroud)

在提交之前,使用stash方法可以让您有机会测试代码是否仍然有效.


srg*_*stm 8

对于那些使用Git Extensions的人:

在"提交"窗口中,选择要部分提交的文件,然后在右窗格中选择要提交的文本,然后右键单击选择并从上下文菜单中选择"显示所选行".

  • Git Extensions 中“Stage selected lines”的键盘快捷键是“s”——对于快速暂存文件的一部分以进行提交非常有用。 (2认同)

Wen*_* Du 7

如果您使用的是 Visual Studio Code (VSCode),那么您很幸运。选择要暂存的范围,然后用于Git: Stage Selected Ranges暂存它们,并根据需要提交。

我录制了一个 gif 来演示我的意思:

在此处输入图片说明


c0f*_*rtc 6

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

:GitGutterStageHunk
Run Code Online (Sandbox Code Playgroud)

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

如果只有部分hunk应该上传vim-fugitive

:Gdiff
Run Code Online (Sandbox Code Playgroud)

允许视觉范围选择,:'<,'>diffput或者:'<,'>diffget分阶段/恢复单独的线条变化.


jas*_*ori 5

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


Fr0*_*0sT 5

使用 TortoiseGit:

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


Bet*_*iga 5

在上一个答案的基础上,如果您更喜欢使用命令行,请输入git add -e myfile来逐行选择要提交的内容,因为此命令将打开具有差异的编辑器,如下所示:

在此处输入图片说明

您可能知道以开头的行+是加法,以开头的行-是删除。所以:

  • 要不进行添加,只需删除该行。
  • 要不进行删除,只需将其替换-为space即可

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

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

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

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

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


Aru*_*run 5

问这个问题已经10年了。我希望这个答案对某人有用。正如这里的答案中提到的,在 GUI 不是一个选项的情况下,Andrew Shadura 的Crecord 扩展有助于带来一个 ncurses 窗口,我们可以在其中选择要提交的行。

设置扩展如下:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord
Run Code Online (Sandbox Code Playgroud)

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

git crecord
Run Code Online (Sandbox Code Playgroud)

这将打开 ncurses 界面,可以使用如下所示的界面。在 ncurses 窗口中按以下键将执行某些操作:

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window
Run Code Online (Sandbox Code Playgroud)

显示示例用法的截屏视频例子