我可以用 git 拆分已经拆分的块吗?
Posted
技术标签:
【中文标题】我可以用 git 拆分已经拆分的块吗?【英文标题】:Can I split an already split hunk with git? 【发布时间】:2011-09-10 17:30:43 【问题描述】:我最近发现了add
命令的git 的patch
选项,我必须说它确实是一个很棒的功能。
我还发现可以通过点击 s 键将一个大块拆分为较小的块,这增加了提交的精度。
但是如果我想要更高的精度,如果分割的块不够小呢?
例如,考虑这个已经分裂的块:
@@ -34,12 +34,7 @@
width: 440px;
-/*#field_teacher_id
- display: block;
- */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label
+#user-register form.table-form .field-type-checkbox label
width: 300px;
如何将 CSS 注释删除仅添加到下一次提交? s
选项不再可用!
【问题讨论】:
【参考方案1】:假设您的example.css
如下所示:
.classname
width: 440px;
/*#field_teacher_id
display: block;
*/
form.table-form #field_teacher + label,
form.table-form #field_producer_distributor + label
width: 300px;
.another
width: 420px;
现在让我们更改中间块中的样式选择器,同时删除一些我们不再需要的旧注释掉的样式。
.classname
width: 440px;
#user-register form.table-form .field-type-checkbox label
width: 300px;
.another
width: 420px;
这很容易,现在让我们提交。 但是等等,我想保持版本控制中更改的逻辑分离,以便进行简单的逐步代码审查,以便我和我的团队可以轻松地搜索提交历史以了解具体细节。
删除旧代码在逻辑上与其他样式选择器更改是分开的。我们将需要两个不同的提交,所以让我们为补丁添加大块。
git add --patch
diff --git a/example.css b/example.css index 426449d..50ecff9 100644 --- a/example.css +++ b/example.css @@ -2,12 +2,7 @@ width: 440px; -/*#field_teacher_id - display: block; - */ - -form.table-form #field_teacher + label, -form.table-form #field_producer_distributor + label +#user-register form.table-form .field-type-checkbox label width: 300px; Stage this hunk [y,n,q,a,d,/,e,?]?
哎呀,看起来更改太接近了,所以 git 已经将它们组合在一起了。
即使尝试通过按 s 来拆分它也会得到相同的结果,因为拆分的粒度不足以改变我们的精度。 更改的行之间需要未更改的行,git 才能自动拆分补丁。
所以,让我们手动编辑按 e
Stage this hunk [y,n,q,a,d,/,e,?]? e
git 将在我们选择的编辑器中打开补丁。
# Manual hunk edit mode -- see bottom for a quick guide @@ -2,12 +2,7 @@ width: 440px; -/*#field_teacher_id - display: block; - */ - -form.table-form #field_teacher + label, -form.table-form #field_producer_distributor + label +#user-register form.table-form .field-type-checkbox label width: 300px; # --- # To remove '-' lines, make them ' ' lines (context). # To remove '+' lines, delete them. # Lines starting with # will be removed. # # If the patch applies cleanly, the edited hunk will immediately be # marked for staging. If it does not apply cleanly, you will be given # an opportunity to edit again. If all lines of the hunk are removed, # then the edit is aborted and the hunk is left unchanged.
让我们回顾一下目标:
如何将 CSS 注释删除仅添加到下一次提交?
我们想把它分成两个提交:
第一次提交涉及删除一些行(注释删除)。
要删除注释行,请不要理会它们,它们已经被标记为跟踪版本控制中的删除,就像我们想要的那样。
-/*#field_teacher_id
- display: block;
- */
第二次提交是一次更改,通过记录删除和添加来跟踪:
删除(删除了旧的选择器行)
为了保留旧的选择器行(在此提交期间不要删除它们),我们希望...
要删除 '-' 行,请将它们设为 ' '
...字面意思是用空格 字符替换减号
-
符号。
所以这三行...
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label
...将变为(notice所有 3 行中第一行的单个空格):
<br>
form.table-form #field_teacher + label,
form.table-form #field_producer_distributor + label
添加(添加了新的选择器行)
为了不关注这次提交期间添加的新选择器行,我们想要...
要删除“+”行,请将其删除。
...字面意思是删除整行:
+#user-register form.table-form .field-type-checkbox label
(奖励:如果您碰巧使用 vim 作为编辑器,请按 dd 删除一行。Nano 用户按 Ctrl +K)
保存时您的编辑器应如下所示:
# Manual hunk edit mode -- see bottom for a quick guide @@ -2,12 +2,7 @@ width: 440px; -/*#field_teacher_id - display: block; - */ form.table-form #field_teacher + label, form.table-form #field_producer_distributor + label width: 300px; # --- # To remove '-' lines, make them ' ' lines (context). # To remove '+' lines, delete them. # Lines starting with # will be removed. # # If the patch applies cleanly, the edited hunk will immediately be # marked for staging. If it does not apply cleanly, you will be given # an opportunity to edit again. If all lines of the hunk are removed, # then the edit is aborted and the hunk is left unchanged.
现在让我们提交。
git commit -m "remove old code"
为了确定,让我们看看上次提交的更改。
git show
commit 572ecbc7beecca495c8965ce54fbccabdd085112 Author: Jeff Puckett <jeff@jeffpuckett.com> Date: Sat Jun 11 17:06:48 2016 -0500 remove old code diff --git a/example.css b/example.css index 426449d..d04c832 100644 --- a/example.css +++ b/example.css @@ -2,9 +2,6 @@ width: 440px; -/*#field_teacher_id - display: block; - */ form.table-form #field_teacher + label, form.table-form #field_producer_distributor + label
完美 - 您可以看到该原子提交中仅包含删除。现在让我们完成这项工作并提交其余的工作。
git add .
git commit -m "change selectors"
git show
commit 83ec3c16b73bca799e4ed525148cf303e0bd39f9 Author: Jeff Puckett <jeff@jeffpuckett.com> Date: Sat Jun 11 17:09:12 2016 -0500 change selectors diff --git a/example.css b/example.css index d04c832..50ecff9 100644 --- a/example.css +++ b/example.css @@ -2,9 +2,7 @@ width: 440px; - -form.table-form #field_teacher + label, -form.table-form #field_producer_distributor + label +#user-register form.table-form .field-type-checkbox label width: 300px;
最后你可以看到最后一次提交只包括选择器的变化。
【讨论】:
Bonus #2: 如果你碰巧使用 VIM 作为你的编辑器,你必须在键盘上按两次“d”来删除一行:D 另外,您可以将+
替换为#
,而不是删除您不想添加的行。结果是一样的,但也许您对删除(并且无法恢复)感到不舒服,或者您想在保存之前进行试验。
而且,对于 vim 来说,r
#
超过了 xD
目标是“我如何才能将 CSS 注释删除仅添加到下一次提交?”,但这些步骤对于它所完成的工作确实令人困惑。 (我们只想在下一次提交中“添加”几行的“删除”。)所以简单地说删除或添加是非常令人困惑的。说明每个步骤完成了什么有助于澄清。【参考方案2】:
如果你使用git add -p
,即使在使用s分割后,你也没有足够小的变化,你可以使用e来编辑补丁直接。
这可能有点令人困惑,但如果您仔细按照按 e 后将打开的编辑器窗口中的说明进行操作那么你会没事的。在您引用的情况下,您可能希望在这些行的开头用空格替换 -
:
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label
... 并删除以下行,即以+
开头的行。如果您随后保存并退出您的编辑器,则只会移除 CSS 注释。
【讨论】:
很酷的解决方案!我看到了,但误解了......我虽然这些更改也会从工作树中删除。 确实,从帮助文本中看不是很明显。实际上,我发现自己经常使用它,因为我认为 git 确实鼓励您使每个提交尽可能精确和美观:) 请注意,您确实必须将其替换为 空格。我尝试了一下,认为我可以删除-
字符,但 Git 抱怨我的补丁不适用。
我猜你删除带有'-'的行并用空格替换'+'的原因是你正在形成一个补丁,其中那些带有'-'的行已经已删除,并且已经添加了带有“+”的行(在补丁的眼睛中)。或者另一种看待它的方式,您实际上是在执行这些字符 (-,+) 所代表的操作(添加或删除一行)。只有带有 '-'s 和 '+'s 的其余行被记录为更改,其余的就是“文件的原样”。
@Filype:我不知道为什么会发生这种情况,恐怕 - 如果你正在运行 git add -p
并用 e
编辑了一个大块,那只会影响上演的内容,而不是你的工作树。【参考方案3】:
一种方法是跳过块,git add
任何你需要的,然后再次运行git add
。如果这是唯一的块,您将能够拆分它。
如果您担心提交的顺序,只需使用git rebase -i
。
【讨论】:
这是我尝试过的,当我再次运行git add -p
时,我的问题中的大块是唯一的,但我无法拆分它。我明白了:Stage this hunk [y,n,q,a,d,/,e,?]?
然后点击 's' 打印帮助。顺便说一句,你的意思是add patch
,而不是patch add
?或者有没有我应该安装的git patch
插件?
你在再次运行之前提交了分阶段的帅哥吗?不,Mercurial 有插件,Git 没有。
不,我没有,我希望它们在同一个提交中(但我想如果你的解决方案有效,我可以使用 --amend 来实现这一点)。我试试看。
正如我的回答所说 → git rebase -i
。哪个比commit --amend
更灵活【参考方案4】:
如果您可以使用 git gui,它允许您逐行进行更改。不幸的是,我不知道如何从命令行执行此操作 - 或者即使有可能。
我过去使用的另一个选项是回滚部分更改(保持编辑器打开),提交我想要的位,撤消并从编辑器重新保存。不是很优雅,但可以完成工作。 :)
编辑(git-gui 用法):
我不确定 git-gui 在 msysgit 和 linux 版本中是否相同,我只使用了 msysgit 之一。但是假设它是相同的,当你运行它时,有四个窗格:左上窗格是您的工作目录更改,左下是您的阶段更改,右上角是所选文件的差异(无论是工作目录或暂存),右下角用于描述提交(我怀疑你不需要它)。当您单击右上角的文件时,您将看到差异。如果您右键单击差异线,您将看到一个上下文菜单。需要注意的两个选项是“stage hunk for commit”和“stage line for commit”。您继续在要提交的行上选择“stage line for commit”,然后就完成了。如果需要,您甚至可以选择多条线并将它们分阶段。您可以随时单击暂存框中的文件以查看您要提交的内容。
至于提交,你可以使用 gui 工具或命令行。
【讨论】:
你的第二个命题很明显,但第一个很有趣,你能再详细一点吗?我安装了git-gui
,但我不知道如何实现你所描述的。
坦克很多!这行得通!我什至可以一键选择我想要暂存的行并为其编制索引。以上是关于我可以用 git 拆分已经拆分的块吗?的主要内容,如果未能解决你的问题,请参考以下文章