ChatGPT解决这个技术问题 Extra ChatGPT

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

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

例如,我如何才能只提交文件中已更改的 30 行中的 15 行?

相关stackoverflow.com/q/34609924/52074:如果您需要将一个大块分成更小的块。
总结:在能力方面:git gui = git add -e > git add -i -p;就方便而言:git gui > git add -i -p > git add -e。所以:当您可以访问 X 时选择 git gui。选择 git add -i -p 用于简单的东西,当您没有或不想使用 X 时。git add -e 用于没有 X 的复杂登台。

2
25 revs, 23 users 20%

您可以使用:

git add --patch <filename>

或简称:

git add -p <filename>

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

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

以下是每个选项的说明:

y 为下一次提交暂存这个大块

不要为下一次提交暂存这个大块

退出;不要上演这个帅哥或任何剩余的帅哥

一个阶段这个大块和文件中的所有后来的大块

不要在文件中暂存这个大块或任何后来的大块

选择一个大块头去

搜索与给定正则表达式匹配的块

让这个大块未定,见下一个未定大块

让这个大块头犹豫不决,看下一个大块头

让这个大块未定,请参阅上一个未定大块

离开这个大块未定,看以前的大块

将当前的大块分割成更小的块

手动编辑当前块然后您可以通过将 +/- 替换为 # 来手动编辑块(感谢 veksen)

然后,您可以通过将 +/- 替换为 # 来手动编辑大块(感谢 veksen)

?打印大块帮助

如果该文件尚未在存储库中,您可以先执行 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


请注意,-p/--patch-i/--interactive 命令内的修补操作的快捷方式,用于启动有用的 Interactive mode
>如果该文件已经暂存,会发生什么?它将仅显示未分级的更改。与 git diff 相同。
如何手动编辑当前大块?我不知道输入 e 后该怎么办。
e 后,您可以通过将 +- 替换为 # 来手动编辑大块
嗯...当我执行 git commit file 时,它会提交所有内容,而不仅仅是我想要的特定更改(即使 git diff --staged 只显示了我想要的特定更改)编辑:git commit -p 将让您选择“hunk "s 并一次性提交;它只提交特定的更改
J
Jakub Narębski

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

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

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


有趣的是,windows.github.com 支持部分文件提交,但最近似乎放弃了它。
@Juri 我认为对部分文件提交的支持又回来了。
@Juri不客气。实际上,我之前从未注意到它曾经存在过——我上周看到它并想“哦,多么了不起的新功能”! :-)
现在 windows.github.com 重定向到重新命名的 GitHub Desktop,它比 Git GUI 更好并且支持部分提交......但不支持提交签名。叹。
@user4942583:GPG 提交签名是一年前添加到 GitHub 桌面的。
I
Ionuț G. Stan

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


对于复杂的补丁,这通常是我最快的方法。
这是一种以细粒度方式向暂存区域添加更改的非常有效且直观的方法。还可以选择多行,并且将添加该选择中的所有更改。
请注意,这不是 gitk,但它包含在 Git Bash for Windows 中;您应该有一个开始菜单条目,或者可以使用命令 git gui 启动它。还有 stage this hunk,它可能比 stage this line 更有用。可能是新的,因为这个答案是 10 年前创建的。
那就是我要找的:)
它似乎也是唯一具有此功能的软件,在 Linux 上受支持:/
0
030

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

添加内容:

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

删除的内容:

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

修改内容:

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

git --help add 上提供了有关 git add 的所有详细信息


如果在某处对如何实际选择这些行(即要输入的实际命令)有明确的解释,这将更加有用。我在文档中找不到。你能添加一个参考吗?
对于那些不喜欢速记选项的人,-e--edit
@Alex theFreedomBanana 添加的引用引用来自 git --help add 中的编辑补丁部分
当您无法在交互式补丁模式下使用 s 缩小块时,这是唯一解决添加/删除行的问题的唯一答案(仅需要 git)。
了解此命令 (git add -e) *不会 * 更改磁盘上的文件内容可能会有所帮助。它只是将部分更改从未分级转移到分级(索引)。
F
François

如果您使用 vim,您可能想尝试名为 fugitive 的出色插件。

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

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


非常感谢您提供此链接。和我需要的完全一样。特别是在可视模式下的 :diffget/:diffput,我可以在其中选择要重置/提交的特定行。所以,再次确保:vim 很棒。
W
Wenfang Du

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

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

https://i.stack.imgur.com/vjyrn.gif


B
Bob Stein

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

https://i.stack.imgur.com/5yQRH.png


我同意 SourceTree 是用于此目的的好工具,因为它为您提供了比命令行更细粒度的控制。
@cupcake 我认为相反,看到 SourceTree 可能使用那些命令行 git 可执行文件,本质上它总是可以通过“命令行”执行相同(或更多)细粒度的操作。
不管 fine-grained 参数我强烈推荐 SourceTree 因为分段大块和单独的行非常容易:i.imgur.com/85bNu4C.png
如果您不想上演“大块头”的一部分怎么办。例如,我只想提交第 50-100 行,而不是第 1-50 行,但 SourceTree 将第 1-100 行视为一个“大块头”
@Sun,您可以单击第 50 行,然后按 shift+单击第 100 行,然后上台。您可以轻松地在 Sourcetree 中上演第 50-100 行 :)
u
user1338062

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

git add -N file
git add -p file

j
jdsumsion

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

像这样:

$ 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 的回答是我通常会做的,除了有时会有很多变化,我可以告诉我在暂存事情时可能会犯错误,我想要一个承诺状态,我可以再次通过。


B
Beto Aveiga

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

https://i.stack.imgur.com/QhSIs.png

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

要不进行添加,只需删除该行。

要不进行删除,只需用空格替换。

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

添加的内容 添加的内容由以“+”开头的行表示。您可以通过删除它们来防止暂存任何添加行。删除的内容:删除的内容由以“-”开头的行表示。您可以通过将“-”转换为“”(空格)来防止暂存它们的删除。修改内容:修改内容由“-”行(删除旧内容)后跟“+”行(添加替换内容)表示。您可以通过将“-”行转换为“”并删除“+”行来防止暂存修改。请注意,仅修改该对的一半可能会给索引带来令人困惑的更改。

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


之前的回答是什么?答案是根据他们拥有的点数存储的。因此,与其他答案相比,您现在的答案与您写它时的位置不同。
我相信引用的答案来自@theFreedomBanana
M
Mark van Lent

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


当我从 Mx shell 窗口运行它时,我经常遇到想要打开编辑器的 git 命令。 magit 会拦截这种疯狂,并为此打开一个新缓冲区吗? (请不要背景-emacs-daemon 提示;无论如何,谢谢,但生命太短了)。
不,据我所知,它不会拦截这个。但不要只相信我的话,因为 (1) 我几乎从不使用 Emacs 中的 shell 窗口,以及 (2) 我通常使用 emacsclient。话虽如此,如果 emacsclient 是您的一个选项,那么至少可以防止打开带有 emacs 的附加窗口,并且在我现有的 Emacs 窗口中打开了“COMMIT_EDITMSG”缓冲区。
马吉特很棒。它允许您通过单次击键(确认删除!)来暂存和取消暂存大块,甚至删除它们。虽然以前是一个相对熟练的 git 命令行用户,但我从来不需要学习 patch 命令,因为 Magit 使它(以及许多其他事情)变得如此简单。实际上,它非常方便,我有时会使用大块删除而不是手动删除,并且使用工作树/索引存储和取消存储来删除和恢复代码块以进行测试 - 换句话说,我使用 Magit 来协助日常编码任务,不仅仅是版本控制。
我认为该链接已过时。在 emacsair.me/2017/09/01/magit-walk-through 中查找暂存更改
谢谢@NikhilWagh,我已经更新了链接
s
srgstm

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

在“提交”窗口中,选择要部分提交的文件,然后在右侧窗格中选择要提交的文本,然后右键单击所选内容并从上下文菜单中选择“暂存选定行”。


Git Extensions 中“暂存选定行”的键盘快捷键是 s - 对于快速暂存部分文件以进行提交非常有用。
我试过这个,但你不能选择删除的行虽然我正在使用 vs 代码
为暂存选择已删除的行在 GitExtensions 中确实有效,并且已经工作了多年。您如何尝试选择和暂存已删除的行?
P
Pang

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

https://i.stack.imgur.com/YoT6c.jpg


方法太简单了。恐怕 Intellij IDEA 正试图杀死 git 试图拯救的最后一个控制台爱好者。
您如何分解右侧添加的内容以仅添加几行? (右侧diff在多行时显示绿色元素) 到目前为止,PyCharm v2020.1.2,您只能在一个块中添加所有连续更改。
@amiabl 你不能(从 v2020.1 开始)。由 youtrack.jetbrains.com/issue/IDEA-186988 跟踪
选择 git commit,然后在 LHS 的 Default Changelist 窗格中,右键单击该文件并选择“Show Diff”。从那里,您可以取消选中您不想提交的差异。
a
andrewsh

问这个问题已经10年了。我希望这个答案对某人有用。正如答案 here 中提到的,在 GUI 不是一个选项的情况下,Andrej Shadura 的 git-crecord tool 有助于带来一个交互式窗口,我们可以在其中选择要提交的行。

设置扩展如下:

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 存储库并按如下方式调用它:

git crecord

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

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

https://i.stack.imgur.com/LDf4u.gif


d
derhoch

就像 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 方法可以让您有机会在提交之前测试您的代码是否仍然有效。


这很好用,但是如果您使用 git commit --amend,之后似乎无法弹出存储,或者有没有办法做到这一点?
c
c0ffeeartc

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

:GitGutterStageHunk

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

如果只上演部分大块vim-fugitive

:Gdiff

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


j
jasongregori

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


F
Fr0sT

使用 TortoiseGit:

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


是的(仅)为此我使用 TortoiseGit。我从 TortoiseSVN 知道它,它很棒
0
0 _

对于 Atom 用户,包 github 包括交互式舞台,采用 git gui 的样式。有关快捷方式,请参见包的 documentation

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


是的,这很容易。选择代码,右键单击,“阶段选择”。
A
Anvesh Yalamarthy

如果它在 Windows 平台上,我认为 git gui 是从 unstaged 文件中 stage/commit 几行的非常好的工具

1. 聪明的:

从未分级的更改部分中选择文件

右键单击需要暂存的代码块

选择 Stage Hunk 进行提交

2. 行明智:

从未分级的更改部分中选择文件

选择要上演的行/行

右键单击并选择 Stage Lines 进行提交

3. 如果要暂存除几行之外的完整文件:

从未分级的更改部分中选择文件

按 Ctrl+T(要提交的暂存文件)

所选文件现在移至分阶段更改部分

选择要上演的行/行

右键单击并选择 UnStage Lines 进行提交


z
zut

对于 emacs,还有 gitsum


b
bartgol

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


截至 2021 年,对于喜欢命令行工具/文本 UI 的人来说,这是最佳选择。
C
Community

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

或简称 git add -p filename.txt

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

... 或者,同样,短格式 git commit -p filename.txt

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


除了更少的错误空间之外,这给您带来了哪些“git add -p filename.txt”?如果您弄乱了部分文件更改,撤消添加比撤消提交更好。
我不知道为什么,但是当我说“n”时,该行被包括在内……当我在第二个大块上说“y”时,它也被包括在内。
C
Croad Langshan

git-meld-index -- 引自网站:

git-meld-index 运行 meld——或任何其他 git difftool(kdiff3、diffuse 等)——以允许您以交互方式暂存对 git 索引(也称为 git 暂存区)的更改。

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

查看更多上下文

查看行内差异

手动编辑并查看“实时”差异更新(每次按键后更新)

导航到更改而不对要跳过的每个更改说“n”

用法

在 git 存储库中,运行:

git meld-index

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

左:临时目录,包含从工作树复制的文件

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

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

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


A
AndiDog

git-cola 是一个很棒的 GUI,并且还内置了此功能。只需选择要暂存的行并按 S。如果未进行选择,则上演完整的大块。


S
Sylvain K.

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

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

当然 Eclipse 更面向 Java,但由于其强大的 git staging 编辑器,它也可以用于其他语言。有一个基于 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 一样直接编辑暂存区域