在Git中只提交一个文件的一部分
当我在Git中更改文件时,如何只提交一些更改?
例如,我如何才能在文件中更改的30行中只提交15行?
你可以使用git add --patch <filename>
(或简称-p
),git会开始将你的文件分解成它认为合理的“hunk”(文件的一部分)。 然后它会提示你这个问题:
Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?
以下是每个选项的说明:
- 为下一次提交做好准备
- ñ不要为下一次提交做好准备
- 退出; 不要把这个大块头或者剩下的任何东西放在一边
- 一个阶段这个大块头和所有后来在文件中的大块头
- d不要把这个大块头或者后面的任何一个大块头放在文件中
- gselect一个大块去
- /search匹配给定的正则expression式的大块
- j留下这个笨蛋,看下一个未定的大块头
- J离开这个笨蛋,看下一个大块头
- k离开这个大块未定,看到以前未定的大块
- K离开这个大块未定,见前面的大块
- 把当前的大块分成小块
- e手动编辑当前的大块
- ? 打印大块的帮助
如果该文件还不在存储库中,则可以先执行git add -N <filename>
。 之后,你可以继续使用git add -p <filename>
。
之后,您可以使用:
git diff --staged
检查你是否进行了正确的修改
git reset -p
to stagage misckedly added hunk
git commit -v
在编辑提交消息时查看您的提交。
注意这和git format-patch
命令有很大的不同,目的是将提交数据parsing为.patch
文件。
未来的参考: https : //git-scm.com/book/en/v2/Git-Tools-Interactive-Staging
你可以使用git add --interactive
或者git 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,也可能有这个function。
git gui在diff视图下提供了这个function。 只需右键单击您感兴趣的行,您应该看到一个“阶段这行提交”菜单项。
我相信, git add -e myfile
是最简单的方法(至less是我的偏好),因为它只是打开一个文本编辑器,让你select你想要的哪一行,哪一行你不行。 关于编辑命令:
添加内容:
添加的内容由以“+”开头的行表示。 您可以通过删除它们来防止暂存任何附加行。
删除的内容:
删除的内容由以“ – ”开头的行表示。 您可以通过将“ – ”转换为“”(空格)来阻止他们的移除。
修改内容:
修改后的内容由“ – ”行(删除旧内容),后跟“+”行(添加replace内容)表示。 您可以通过将“ – ”行转换为“”来防止修改,并删除“+”行。 请注意,修改只有一半的对可能会引起混乱的索引变化。
有关git add
每个细节都可以在git --help add
如果您使用的是vim,您可能需要尝试一下名为“ 逃犯”的优秀插件。
你可以在工作副本和索引之间看到文件的差异:Gdiff
,然后使用经典的vim diff命令(如dp
向索引添加行或块。 保存索引中的修改,并提交:Gcommit
,你就完成了。
非常好的介绍性截屏(见第2部分 )。
我强烈build议使用Atlassian的SourceTree 。 (它是免费的。)它使这个微不足道的。 您可以快速轻松地分阶段代码或单独的代码行。
当我有很多的变化,并最终会从变化创build一些提交,然后我想暂时保存我的起点。
喜欢这个:
$ 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的答案就是我通常所做的,除了有时候会有很多的变化,而且我可以告诉我在做事的时候可能会犯一个错误,而且我想要一个可以重返的状态。
值得注意的是,使用git add --patch
作为新文件,你需要首先添加文件索引与git add --intent-to-add
:
git add -N file git add -p file
你应该使用emacs,看看Magit ,它提供了一个emacs的git界面。 它支持staging hunk (文件的部分)相当好。
就像jdsumsion的回答一样,你也可以隐藏你当前的工作,然后使用一个diff工具像meld从存储中提取选定的更改。 这样,你甚至可以手动编辑hunk,这很容易,在git add -p
有点痛苦:
$ git stash -u $ git difftool -d -t meld stash $ git commit -a -m "some message" $ git stash pop
在提交之前,使用存储方法可以让您有机会testing代码是否仍然有效。
vim-gitgutter插件可以在没有离开vim编辑器的情况下使用
:GitGutterStageHunk
除此之外,它还提供了其他很酷的function,如一些现代IDE中的差异标志列
如果只有一部分人应该上演vim-fagitive
:Gdiff
允许视觉范围select,然后:'<,'>diffput
或:'<,'>diffget
阶段/恢复单个行更改。
对于那些使用Git扩展的人 :
在“提交”窗口中,select要部分提交的文件,然后在右窗格中select要提交的文本,然后右键单击所选内容,然后从上下文菜单中select“选定的行”。
尝试了git add -p filename.x
,但在Mac上,我发现gitx( http://gitx.frim.nl/或https://github.com/pieter/gitx )更容易提交我想要的线。
随着TortoiseGit:
右键单击该文件并使用
Context Menu → Restore after commit
。 这将创build一个文件的副本。 然后你可以编辑这个文件,例如在TortoiseGitMerge中,撤销所有你不想提交的改变。 保存这些更改后,您可以提交该文件。
对于emacs还有gitsum
git-meld-index – 从网站引用:
git-meld-index运行meld – 或其他任何git difftool(kdiff3,diffuse等) – 允许您交互式地对git索引(也称为git staging区域)进行更改。
这与git add -p和git add –interactive的function类似。 在某些情况下,融合比git add -p更容易/更快速。 那是因为meld允许你,例如:
- 看更多的上下文
- 见线内差异
- 手动编辑并查看“实时”差异更新(每次按键后更新)
- 导航到一个变化,不要说'n'你想要跳过每一个变化
用法
在一个git仓库中运行:
git meld-index
你会看到meld(或你configuration的git difftool)popup:
LEFT :从工作树复制的临时目录
RIGHT :包含索引内容的临时目录。 这还包括那些还没有在索引中,但在工作副本中被修改或未被跟踪的文件 – 在这种情况下,您将会看到来自HEAD的文件内容。
编辑索引(右侧),直到快乐。 记得在需要时进行保存。
完成之后,closuresmeld,git-meld-index会更新索引以匹配刚刚编辑的meld右侧临时目录的内容。
正如上面的一个答案所示,您可以使用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等)来select要包含在提交中的行。
如果它在Windows
平台上,在我看来, git gui
是最好的工具,从unstaged
文件中stage
/ commit
几行
1.聪明:
- 从未加
unstagged Changes
部分select文件 - 右键单击需要上演的代码块
- select
Stage Hunk for commit
2.明智的:
- 从未加
unstagged Changes
部分select文件 - select要进行的线/线
- select
Stage Lines for commit
3.如果您想要完整的文件,除了几行:
- 从未加
unstagged Changes
部分select文件 - 按下
Ctrl+T (Stage file to commit)
- 所选文件现在移到
Staged Changes
部分 - select要进行的线/线
- select
UnStage Lines for commit
git-cola是一个很棒的graphics用户界面,并且内置了这个function。 只需select线路,然后按S键。 如果没有select,完整的大块是上演。