当我在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的情况下进行复杂的过渡。

#1 楼

您可以使用git add --patch <filename>(或简称-p),而git会开始将您的文件分解为它认为是明智的“大头”(文件的一部分)。然后它将提示您以下问题:

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


以下是每个选项的说明:



y为下一次提交暂存此大块

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

q quit;请勿暂存此暂存器或任何剩余的暂存器

暂不暂存此暂存器,而文件中的所有后续暂存器


g中选择一个大块以转到

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

j尚未确定该大块,请参见下一个尚未决定的大块

J尚未决定这个大块,请参阅下一个

k不要决定这个大块,请参见上一个未确定的目标

K尚未确定,请参阅先前的块

将当前块拆分为较小的块

手动编辑当前块

? 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工具-交互式暂存

评论


注意-p /-patch是-i /-interactive命令(用于启动有用的交互方式)中的patch操作的快捷方式,可能很有用。

–tutuDajuju
15年2月15日在9:30

>如果该文件已经上演会怎样?它将仅显示未分阶段的更改。和git diff一样。

– Eugen Konkov
2015年6月3日,9:52

如何手动编辑当前大块?输入e后我不知道该怎么办。

– su
15年11月1日于13:47

按下e后,您可以通过用#代替+或-手动编辑大块

–veksen
15年11月24日在20:31

这很棒,但是现在我该如何实际推动它呢?如果我做git push它说已经是最新的了。如果我做git diff,我会看到我说的帅哥。如果我做git diff --staged,我看到我要推送的提交。假设我可以推动提交,如何删除我拒绝的帅哥?

–碎肉
17年1月12日23:37



#2 楼

您可以使用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)也可能具有此功能。

评论


有趣的是,windows.github.com支持部分文件提交,但最近似乎删除了它。

–朱里
2014年9月1日20:41在

@Juri我认为部分文件提交的支持又回来了。

– Ela782
15年2月24日在10:40

@Juri不客气。我实际上从来没有注意到它曾经存在过-上周我看到了它,然后想到:“哦,这真是一个了不起的新功能”! :-)

– Ela782
15年2月24日在17:25

如今,windows.github.com重定向到重新命名的GitHub桌面,它比Git GUI更好,并且支持部分提交...但是不支持提交签名。叹。

–user4942583
18年2月2日,0:37

#3 楼

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

评论


对于复杂的补丁程序,这通常对我来说是最快的方法。

– hochl
2015年4月8日在7:35

这是一种非常有效且直观的方式,可以以精细的方式将更改添加到登台区域。也可以选择多行,并且将添加该选择中的所有更改。

– jox
2015年4月26日在23:13

请注意,这不是gitk,但Windows的Git Bash附带了它。您应该有一个开始菜单项,或者可以使用命令git gui启动它。还有一个阶段,这个阶段可能比阶段阶段更有用。自从10年前创建此答案以来,它可能是新的。

–克里斯
19-11-26在16:37



那就是我一直在寻找的东西:)

– StayCool
12月18日9:24

#4 楼

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

添加的内容:


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


已删除的内容:


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


修改后的内容:



修改后的内容是用“-”行表示(删除旧内容),然后用“ +”行表示(添加替换内容)。您可以通过将“-”行转换为“”并删除“ +”
行来防止进行修改。请注意,仅修改一对货币对中的一半可能会导致索引混乱。


有关git add的每个详细信息都可以在git --help add上找到

评论


如果在某处对如何实际选择这些行(即要输入的实际命令)有明确的解释,这将更有用。我在文档中找不到一个。您可以添加参考吗?

– Alex
2016年9月6日在22:16

对于那些不喜欢速记选项的人,-e是--edit。

–科林尼亚
16年11月15日在13:44

@Alex TheFreedomBanana添加的引用引号来自git --help add中的EDITING PATCHES部分。

–兰德尔
17年1月11日23:04



这是唯一的答案(仅需要git),当您无法在交互式补丁程序模式下使用s减小块的大小时,它可以解决按行添加/删除行的问题。

–cdosborn
17年4月13日在15:54

了解此命令(git add -e)*不会*更改磁盘上的文件内容可能会有所帮助。它只是将部分更改从非暂存移动到暂存(索引)。

–耿鹏和
19年7月5日在15:50



#5 楼

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

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

这里的介绍性视频非常好(请参见第2部分)。

评论


非常感谢您提供此链接。完全一样。尤其是在可视模式下的:diffget /:diffput,在这里我可以选择要重置/提交的特定行。因此,请再次确认:vim很棒。

– Goodniceweb
15年7月28日在9:01

#6 楼

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



评论


我同意SourceTree是用于此目的的好工具,因为与通过命令行提供的功能相比,它可以为您提供更细粒度的控制。

–user456814
2014年8月12日14:29
@cupcake我反过来说,看到SourceTree可能使用了这些命令行git可执行文件,从本质上讲,总是可以通过“命令行”执行相同(或更多个)细粒度的操作。

–tutuDajuju
15年2月15日在9:25

不管细粒度的论点,我都强烈建议SourceTree作为暂存大块和单独的行是非常容易的:i.imgur.com/85bNu4C.png

–火星罗伯逊
2015年6月1日上午10:57

@tutuDajuju在这种情况下,我不确定那是真的。 SourceTree能够逐行选择要登台的部分。您不必上演整个大礼;您可以在大块中间上演2行。我不知道它是如何实现的。 (目前,我正尝试解决SourceTree无法为未跟踪的文件暂存特定行的问题。我在这里着手寻找解决方法,只是发现git似乎没有提供逐行功能一点也不行。)

– jpmc26
2015年8月11日在20:17



@Sun,您可以单击第50行,并按住Shift键并单击第100行,然后进行登台。您可以轻松地在Sourcetree中暂存50-100行:)

–ryan123
18/12/17在12:14

#7 楼

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

git add -N file
git add -p file


#8 楼

当我进行很多更改时,最终将根据更改创建一些提交,那么我想在暂存之前临时保存我的起点。

像这样:

$ 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


为什么我的答案是我通常要做的,除了有时会有很多变化,而且我可以告诉我在上演事情时可能会犯错,并且我希望我可以回到一种确定的状态第二遍。

#9 楼

如果您使用emacs,请看一下Magit,它为emacs提供了git界面。它很好地支持暂存块(文件的一部分)。

评论


从M-x Shell窗口运行git命令时,我经常会想打开一个git命令。 magit是否会拦截这种疯狂行为,并为此打开一个新的缓冲区? (请不要提供background-emacs-daemon提示;无论如何要感谢,但生活太短了)。

–user2066657
18年5月18日在23:27

不,据我所知它不会截获此消息。但是,不要只听我的话,因为(1)我几乎从未在Emacs中使用shell窗口,并且(2)我通常使用emacsclient。话虽如此,如果您可以选择emacsclient,那么至少可以防止打开带有emacs的其他窗口,并在现有的Emacs窗口中打开“ COMMIT_EDITMSG”缓冲区。

–马克·范·伦特
18年5月30日在19:43



#10 楼

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



评论


方法太简单了。恐怕Intellij IDEA试图杀死git试图保存的最后一个控制台爱好者。

–分钟
6月16日18:37



如何分解在右侧添加的内容,仅添加几行? (当它位于多行上时,将显示右侧差异上的绿色元素)到目前为止,PyCharm v2020.1.2只能将所有连续更改添加到一个块中。

– amiabl
6月23日10:31

@amiabl不能(自v2020.1起)。由youtrack.jetbrains.com/issue/IDEA-186988跟踪

–霍尔格·布兰德尔(Holger Brandl)
6月23日10:48

#11 楼

对于使用Git Extensions的用户:

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

评论


Git Extensions中“选定行的阶段”的键盘快捷键是s -对快速分段文件的提交非常有用。

–炼金术师
17年2月3日在16:13

我尝试了这个,但是尽管您正在使用vs代码,但是您无法选择已删除的行

–iamafasha
6月13日18:32

选择已删除的行进行暂存确实可以在GitExtensions中使用,并且已经使用了很多年。您如何尝试选择和暂存已删除的行?

– Eli_B
8月7日15:05

#12 楼

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



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


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

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


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

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

修改后的内容:
修改后的内容用“- “行(删除旧的
内容),后跟“ +”行(添加替换内容)。
您可以通过将“-”行转换为
“”来防止进行修改删除“ +”行。请注意,仅修改
对的一半可能会导致索引混乱。


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

评论


先前的答案是什么?根据答案的分数来存储答案。因此,与其他答案相比,您的答案现在与撰写本文时的位置不同了。

–库拉金
1月5日在1:14

我相信引用的答案来自@theFreedomBanana

– K.符号
1月13日8:32

#13 楼

就像jdsumsion的答案一样,您也可以隐藏当前工作,然后使用diff工具(例如meld)从存储中提取选定的更改。这样,您甚至可以非常轻松地手动编辑帅哥,当在git add -p中使用时,这有点麻烦:

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


使用隐藏方法使您有机会进行测试,如果您的代码仍然有效,则在提交之前。

评论


这很好用,但是如果您使用git commit --amend,似乎您以后无法弹出存储,还是有办法吗?

–马克
2014年4月5日在12:42

#14 楼

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

:GitGutterStageHunk


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

如果应该仅将大块的部分暂存为Vim逃犯

:Gdiff


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

#15 楼

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

#16 楼

提出这个问题已有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


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


截屏显示了示例用法

#17 楼

使用TortoiseGit:


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


#18 楼

对于Atom用户,包github包含git gui样式的交互式暂存。有关快捷方式的信息,请参阅软件包的文档。

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

#19 楼

如果在Windows平台上,我认为git guistage / commit文件中来自unstaged文件的几行的很好的工具

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



#20 楼

对于emacs,还有gitsum

#21 楼

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

或缩写形式的
git add -p filename.txt

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

...或,再次是简短的
git commit -p filename.txt

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

评论


除了减少错误的余地之外,您还能通过“ git add -p filename.txt”获得什么呢?如果您弄乱了部分文件更改,则撤消添加比撤消提交要好。

– CTMacUser
14年8月18日在20:38

我不知道为什么,但是当我说'n'时,这行被包括在内....当我在第二个大块头中说'y'时,它也被包括在内。

–碎肉
16年4月15日在5:53

#22 楼

git-meld-index-从网站引用:

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

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


查看更多上下文
查看行内差异
手工编辑并查看“实时”差异更新(在每次按键后更新)
导航更改,而不对要跳过的每个更改说“ n”

用法

在git存储库中,运行:

git meld-index


您会看到以下对话框弹出融合(或配置的git difftool):

左:从工作中复制的临时目录继续文件tree

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

编辑索引(右侧) )直到幸福。记住要在需要时保存。

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

#23 楼

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