我有两个工作分支,主人和论坛,我刚刚在论坛分支做了一些修改,我想要樱桃挑选主人。但不幸的是,我想要挑选的提交还包含一些我不想要的修改。
解决方案可能会以某种方式删除错误的提交,并将其替换为两个单独的提交,一个包含我想在master中选择的更改,另一个包含不属于那里的更改。
我已经尝试过了
git reset --hard HEAD^
删除了所有更改,因此我不得不返回
git reset ORIG_HEAD
所以我的问题是,将拆分最后一次提交的最佳方法是什么?两个单独的提交?
答案 0 :(得分:327)
您应该使用索引。执行混合重置(“git reset HEAD ^”)后,添加 第一组更改到索引中,然后提交它们。然后提交 其余部分。
您可以使用“git add”将文件中所做的所有更改都放入索引中。如果你 不希望在文件中进行每次修改,只有其中一些修改,你 可以使用“git add -p”。
我们来看一个例子。假设我有一个名为myfile的文件,其中包含 以下文字:
something
something else
something again
我在上次提交时对其进行了修改,现在它看起来像这样:
1
something
something else
something again
2
现在我决定将它分成两部分,我想要插入 第一行提交的第一行,以及最后一行的插入 在第二次提交。
首先我回到HEAD的父母,但我想保留文件系统中的修改, 所以我使用“git reset”而没有参数(这将做一个所谓的“混合” 复位):
$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
现在我使用“git add -p”添加我想要提交给索引的更改(= I 他们)。 “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
然后我做了第一次改变:
$ git commit -m "Added first line"
[master cef3d4e] Added first line
1 files changed, 1 insertions(+), 0 deletions(-)
现在我可以提交所有其他更改(即最后一行中的数字“2”):
$ git commit -am "Added last line"
[master 5e284e6] Added last line
1 files changed, 1 insertions(+), 0 deletions(-)
让我们检查日志以查看我们提交的内容:
$ 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
答案 1 :(得分:81)
splitme
)分成两部分。splitme
之前与一个人进行互动。 splitme
。 如果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
如果我想首先提交拆分文件,那么我会再次重新定义-i并切换顺序
git rebase -i splitme^
# swap order of splitme and 'just some files'
答案 2 :(得分:52)
要将当前提交更改为两次提交,您可以执行以下操作。
或者:
git reset --soft HEAD^
这撤消了最后一次提交,但让所有事情都上演了。然后,您可以取消暂存某些文件:
git reset -- file.file
可选择恢复这些文件的部分内容:
git add -p file.file
进行新的第一次提交:
git commit
阶段并在第二次提交中提交其余更改:
git commit -a
或者:
撤消并取消上一次提交的所有更改:
git reset HEAD^
有选择地进行第一轮改变:
git add -p
提交:
git commit
提交其余的更改:
git commit -a
(在任一步骤中,如果您取消添加了全新文件的提交并想要将其添加到第二次提交,则必须手动将其添加为commit -a
,只会对已经跟踪的文件进行更改。 )
答案 3 :(得分:22)
运行git gui
,选择“修改上次提交”单选按钮,然后取消(提交> Unstage From Commit,或 Ctrl - U )更改你不想进入第一次提交。我认为这是最简单的方法。
你可以做的另一件事就是在不提交(git cherry-pick -n
)的情况下挑选更改,然后手动或使用git gui
在提交之前选择所需的更改。
答案 4 :(得分:15)
git reset HEAD^
答案 5 :(得分:13)
我很惊讶没有人建议git cherry-pick -n forum
。这将从最新的forum
提交中暂存更改但不提交它们 - 然后您可以reset
远离您不需要的更改并提交您想要保留的内容。
答案 6 :(得分:3)
git checkout HEAD~1 -- files with unwanted changes
和git commit
。如果不是,具有混合更改的文件可以部分暂存git reset file
和git add -p file
作为中间步骤。 )将其称为还原。git revert HEAD
- 进行另一次提交,即添加不需要的更改。这是双重还原 git rebase -i HEAD~3
)。此提交现在可以免除不需要的更改,因为这些更改是在第二次提交中。答案 7 :(得分:1)
既然你正在挑选,你可以:
Statement
添加了cherry-pick
选项。--no-commit
并使用reset
,add --patch
或add --edit
来展示您想保留的内容。add
分阶段的变化。
commit
命令添加--reuse-message=<old-commit-ref>
或--reedit-message=<old-commit-ref>
个选项。commit
打开未分期更改。另一种方法,保留或编辑原始提交消息:
reset --hard
原始提交正常。cherry-pick
进行撤消。
add
实现樱桃选择提交的逆转。
答案 8 :(得分:0)
这可能是针对大量提交且需要将少量文件移入新提交的情况的另一种解决方案。如果要从HEAD的最后一次提交中提取一组<path>
文件并将其全部移至新的提交,这将起作用。如果需要多次提交,则可以使用其他解决方案。
首先将补丁添加到暂存区域和未暂存区域,这些区域将包含更改以分别将代码还原到修改之前和修改之后:
git reset HEAD^ <path>
$ git status
On branch <your-branch>
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: <path>
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: <path>
要了解将会发生什么(箭头和注释不属于命令):
git diff --cached -> show staged changes to revert <path> to before HEAD
git diff -> show unstaged changes to add current <path> changes
在上一次提交中还原<path>
个更改:
git commit --amend -> reverts changes on HEAD by amending with staged changes
使用<path>
更改创建新的提交:
git commit -a -m "New Commit" -> adds new commit with unstaged changes
这具有创建一个新提交的作用,其中包含从上一次提交中提取的更改。
答案 9 :(得分:0)
您可以使用git rebase -i <commit>
,其中<commit>
是您想保持原样的最新提交。在每个要插入新拆分提交的位置添加一个break
。然后在每个中断处,使用git checkout -p <commit containing parts you want>
提取要拆分的部分并提交。然后git rebase --continue
从以后的提交中删除那些部分。
对于拆分最近提交的简单情况,它看起来像:
$ git rebase -i HEAD^
# add 'break' at the start
$ git checkout -p master # or whatever your branch is called
# choose the parts you want to split out
$ git commit
# commit the newly-split-out parts
$ git rebase --continue
# rebase the remaining parts of the change onto the split-out parts
这是假设您希望以后的提交保留原始提交消息;我通常就是这种情况(进行一些准备性更改)。