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

时间:2009-07-06 02:25:02

标签: git git-commit

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

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

25 个答案:

答案 0 :(得分:3301)

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

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

以下是每个选项的说明:

  • y 为下次提交暂存这个大块
  • n 不要为下一次提交暂存此hunk
  • q 退出;不要把这个大块头或任何剩下的帅哥放在一边
  • a 阶段这个大块头以及所有后来的文件中的帅哥
  • d 不要在文件中暂存此hunk或任何后来的帅哥
  • g 选择一个大块来转到
  • / 搜索与给定正则表达式匹配的大块
  • j 留下这个大块未定,看下一个未定的大块头
  • J 留下这个帅哥未定,见下一个帅哥
  • k 让这个帅哥犹豫不决,看看以前未定的大块头
  • K 留下这个大块未定,见上一个大块头
  • s 将当前的大块分成较小的帅哥
  • e 手动编辑当前的hunk
  • print hunk help

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

之后,您可以使用:

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

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

未来参考:Git Tools - Interactive Staging

答案 1 :(得分:232)

您可以使用git add --interactivegit add -p <file>,然后使用git commit git commit -a);请参阅git-add联机帮助页中的交互模式,或者只需按照说明操作。

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

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

答案 2 :(得分:127)

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

答案 3 :(得分:67)

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

添加内容:

  

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

删除了内容:

  

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

修改内容:

  

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

有关git add的所有详细信息均可在git --help add

上找到

答案 4 :(得分:42)

如果你使用的是vim,你可能想尝试一下名为fugitive的优秀插件。

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

非常好的介绍性截屏视频here(参见esp。part 2)。

答案 5 :(得分:28)

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

enter image description here

答案 6 :(得分:24)

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

git add -N file
git add -p file

答案 7 :(得分:21)

当我进行了大量更改,并最终会根据更改创建一些提交时,我想暂时保存起点。

像这样:

$ 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的答案就是我通常所做的,除非有时会有很多变化,我可以告诉我在进行事情时可能会犯错误,我想要一个承诺状态,我可以再次进行第二次传球。

答案 8 :(得分:12)

如果您使用emacs,请查看Magit,它为emacs提供git界面。它很好地支持staging hunks(部分文件)。

答案 9 :(得分: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

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

答案 10 :(得分:8)

对于使用 Git Extensions 的人:

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

答案 11 :(得分:7)

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

enter image description here

答案 12 :(得分:6)

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

进行分段
:GitGutterStageHunk

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

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

:Gdiff

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

答案 13 :(得分:5)

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

答案 14 :(得分:4)

使用TortoiseGit:

  

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

答案 15 :(得分:4)

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

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

enter image description here

答案 16 :(得分:3)

对于Atom个用户,程序包github包含git gui样式的交互式登台。有关快捷方式,请参阅包documentation

使用Atom可以处理背景较暗的主题(默认情况下,git gui具有白色背景)。

答案 17 :(得分:2)

git-meld-index - 引自网站:

git-meld-index运行meld - 或任何其他git difftool(kdiff3,diffuse等) - 允许您以交互方式对git索引(也称为git staging区域)进行更改。

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

  • 查看更多背景信息
  • 参见行内差异
  • 手动编辑并查看“实时”差异更新(每次按键后更新)
  • 导航到更改,而不是对要跳过的每个更改都说'n'

<强>用法

在git存储库中,运行:

git meld-index

你会看到meld(或你配置的git difftool)弹出:

LEFT :从工作树中复制的临时目录合并文件

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

编辑索引(右侧)直到开心。记得在需要时保存。

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

答案 18 :(得分:2)

对于emacs,还有gitsum

答案 19 :(得分:2)

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

enter image description here

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

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

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

  

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

     

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

     

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

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

答案 20 :(得分:1)

如上面one answer所示,您可以使用 git add --patch filename.txt

或短文 git add -p filename.txt

...但是对于已存在于您的存储库中的文件,最好直接在commit命令上使用--patch标志(如果您使用的是最新版本的git): git commit --patch filename.txt

......或者,简称 git commit -p filename.txt

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

答案 21 :(得分:1)

问这个问题已有10年了。我希望这个答案对某人有用。如答案here所述,在没有GUI的情况下,Andrew Shadura的crecord extension帮助打开ncurses窗口,我们可以在其中选择要提交的行。

按如下所示设置扩展名:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

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

git crecord

这将打开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

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

答案 22 :(得分:1)

您可以使用Eclipse IDE,可以将每个修改的本地文件与暂存区进行比较,在此并排差异视图中,您可以自由选择从本地复制到暂存区的哪个大块,或者相反,回滚来自舞台区域的局部变化。

但是还有更多:),所有图形化的 git 客户端也都做那个大块的暂存(git add -p),但我知道没有一个可以做到:直接在暂存区域中进行编辑,因此可以在同一行或相同的大块上进行多次更改收到更多罚款(甚至写入/删除/更新本地从未存在的内容),例如在补丁级别工作但没有破坏补丁内容的风险的“git add -e”。 此外,由于它与 diff 视图中的常规文本编辑器一起使用,因此您有语法颜色可以提供帮助,并且您可以执行文本替换操作(更改所有缩进类型,重命名在许多地方使用的局部变量,...)以开始单独提交一些在提交“真正的”更改之前重新格式化/重构,但不要在同一个提交中嵌入所有文件更改。

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

答案 23 :(得分:0)

如果它位于Windows平台上,我认为git gui是来自stage文件

commit / unstaged几行的非常好的工具

<强> 1。 Hunk明智:

  • 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

答案 24 :(得分:0)

git-cola是一个很棒的GUI,内置了这个功能。只需选择要分段的行,然后按 S 。如果没有做出选择,则完成整个大块。