如何在Git中将最后一次提交拆分为两次

Jak*_*old 276 git version-control

我有两个工作分公司,大师论坛,我刚刚作出了一些修改论坛的分支,我想摘樱桃进入.但不幸的是,我想要挑选的提交还包含一些我不想要的修改.

解决方案可能是以某种方式删除错误的提交并将其替换为两个单独的提交,一个包含我想在master中选择的更改,另一个不属于那里.

我试过了

git reset --hard HEAD^
Run Code Online (Sandbox Code Playgroud)

删除了所有更改,所以我不得不回去

git reset ORIG_HEAD
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,最后一次提交分成两个单独的提交的最佳方法什么?

hcs*_*s42 330

你应该使用索引.执行混合重置(" git reset HEAD ^")后,将第一组更改添加到索引中,然后提交它们.然后完成其余的工作.

您可以使用" git add "将文件中所做的所有更改都放到索引中.如果您不想对文件中的每个修改进行分段,只需对其中的一些进行修改,则可以使用"git add -p".

我们来看一个例子吧.假设我有一个名为myfile的文件,其中包含以下文本:

something
something else
something again
Run Code Online (Sandbox Code Playgroud)

我在上次提交时对其进行了修改,现在它看起来像这样:

1
something
something else
something again
2
Run Code Online (Sandbox Code Playgroud)

现在我决定将它拆分为两个,并且我希望第一行的插入在第一次提交中,并且插入最后一行将在第二次提交中.

首先我回到HEAD的父级,但我想在文件系统中保留修改,所以我使用"git reset"而不使用参数(这将进行所谓的"混合"重置):

$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
Run Code Online (Sandbox Code Playgroud)

现在我使用"git add -p"添加我想要提交给索引的更改(=我将它们分级)."git add -p"是一个交互式工具,它会询问您应该将哪些文件更改添加到索引中.

$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s    # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y  # yes, I want to stage this
@@ -1,3 +2,4 @@
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n   # no, I don't want to stage this
Run Code Online (Sandbox Code Playgroud)

然后我做了第一次改变:

$ git commit -m "Added first line"
[master cef3d4e] Added first line
 1 files changed, 1 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)

现在我可以提交所有其他更改(即最后一行中的数字"2"):

$ git commit -am "Added last line"
[master 5e284e6] Added last line
 1 files changed, 1 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)

让我们检查一下日志,看看我们有什么提交:

$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...

    Added last line

Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
 something
 something else
 something again
+2

Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...

    Added first line

Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again
Run Code Online (Sandbox Code Playgroud)

  • 在过去的一个半星期里,我已经慢慢习惯了 Mercurial 的 git,并且有一个方便的快捷命令“git reset [--patch|-p] <commit>”,您可以使用它来省去以下麻烦:重置后必须“git add -p”。我对吗?使用 git 1.7.9.5。 (2认同)
  • 这里有一些关于这种技术的更多信息,包括如果它是一个较旧的提交,或者您需要将N提交更改为M提交的更改:http://emmanuelbernard.com/blog/2014/04/14/split-a-commit- in-two-with-git /. (2认同)

spa*_*azm 81

目标:

  • 我想将过去的commit(splitme)分成两部分.
  • 我想维护提交消息.

计划:

  1. 改变以前的互动splitme.
  2. 编辑splitme.
  3. 重置文件以拆分为第二次提交.
  4. 修改提交,维护消息,根据需要进行修改.
  5. 添加从第一次提交中拆分的文件.
  6. 提交新消息.
  7. 继续改变.

如果splitme是最近的提交,则可以跳过rebase步骤(1和7).

git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue
Run Code Online (Sandbox Code Playgroud)

如果我想首先提交拆分文件,我会再次重新设置-i并切换顺序

git rebase -i splitme^
# swap order of splitme and 'just some files'
Run Code Online (Sandbox Code Playgroud)

  • 重要的是要注意`git reset`的` - $ files`参数.通过路径,`git reset`将这些文件恢复到引用提交的状态,但不会更改任何提交.如果你离开路径,那么你将在下一步"丢失"你想要修改的提交. (9认同)
  • `git reset HEAD^` 是拼图中缺失的一块。与“-p”也可以很好地配合。谢谢! (2认同)
  • 与接受的答案相比,此方法可以防止您再次复制和粘贴第一个提交消息. (2认同)
  • @duelinmarkers确切地说,`git reset HEAD^ .`将*index*重置为父提交,但HEAD保留在当前提交上,而`git reset HEAD^`将*HEAD*重置为父提交。因此,后续的“git commit --amend”将*替换*第一种情况下的当前提交,以及第二种情况下的父提交。这就是为什么在第二种情况下,您应该执行“git commit”来*创建*一个新的提交(这是[那个答案](/sf/answers/100814031/)中的方法)。该答案中的方法的优点是可以访问修改后的提交消息。 (2认同)

CB *_*ley 52

要将当前提交更改为两个提交,您可以执行以下操作.

或者:

git reset --soft HEAD^
Run Code Online (Sandbox Code Playgroud)

这撤消了最后一次提交,但让所有事情都上演了.然后,您可以取消暂存某些文件:

git reset -- file.file
Run Code Online (Sandbox Code Playgroud)

可以选择重新放置这些文件的部分:

git add -p file.file
Run Code Online (Sandbox Code Playgroud)

进行新的第一次提交:

git commit
Run Code Online (Sandbox Code Playgroud)

阶段并在第二次提交中提交其余更改:

git commit -a
Run Code Online (Sandbox Code Playgroud)

要么:

撤消和取消上次提交的所有更改:

git reset HEAD^
Run Code Online (Sandbox Code Playgroud)

选择性地进行第一轮变革:

git add -p
Run Code Online (Sandbox Code Playgroud)

承诺:

git commit
Run Code Online (Sandbox Code Playgroud)

提交其余更改:

git commit -a
Run Code Online (Sandbox Code Playgroud)

(在任一步骤中,如果您取消添加了全新文件的提交并希望将其添加到第二次提交,则必须手动将其添加为commit -a仅对已跟踪文件的阶段更改.)


Mic*_*ker 22

运行git gui,选择"修改上次提交"单选按钮,然后取消暂存(提交> Unstage From Commit或Ctrl- U)更改,您不想进入第一次提交.我认为这是最简单的方法.

您可以做的另一件事是在没有提交(git cherry-pick -n)的情况下挑选更改,然后手动或git gui在提交之前选择所需的更改.


sem*_*art 15

git reset HEAD^
Run Code Online (Sandbox Code Playgroud)

--hard正在扼杀你的变化.


dah*_*byk 13

我没有人建议我感到惊讶git cherry-pick -n forum.这将从最新forum提交中暂存更改但不提交它们 - 然后您可以reset远离不需要的更改并提交您想要保留的内容.