如果不创建一个分支并在一个新分支上做一堆奇怪的工作,那么在将一个提交提交到本地存储库之后,是否有可能将其分解为几个不同的提交?


当前回答

git rebase-我会做的。

首先,从一个干净的工作目录开始:git状态应该显示没有挂起的修改、删除或添加。

现在,您必须决定要拆分哪些提交。

A) 拆分最近的提交

要拆分最近的提交,首先:

$ git reset HEAD~

现在,以通常的方式单独提交这些片段,根据需要生成任意数量的提交。

B) 将提交拆分到更远的位置

这需要重新定基,即重写历史。要指定正确的提交,您有几个选项:

如果是三次提交,那么$git rebase-i头~3其中3是返回的提交数。如果它在树上比你想数的更远,那么$git rebase-i 123abcd~其中123abcd是要拆分的提交的SHA1。如果您位于要合并到主节点的其他分支(例如,要素分支)上:$git rebase-i主

当您获得rebase编辑屏幕时,找到您想要拆分的提交。在该行的开头,用edit(简称e)替换pick。保存缓冲区并退出。在您要编辑的提交之后,回扣将立即停止。然后:

$ git reset HEAD~

以通常的方式单独提交各个部分,根据需要生成多个提交。

最后

$ git rebase --continue

其他回答

大多数现有的答案都建议使用交互式rebase-git rebase-i或类似的方法。对于像我这样害怕“互动”的人来说,下楼梯时喜欢抓住扶手,这里有一个选择。

假设您的历史看起来像…->P–>Q–>R–>…–>Z=mybranch,并且您希望将P–>Q分成两个提交,以P–>Q1–>Q'–>R'–>…Z'=mybranch结束,其中Q'、R'等处的代码状态与Q、R等相同。

在开始之前,如果你是偏执狂,请备份我的分支,这样你就不会冒失去历史的风险:

git checkout mybranch
git checkout -b mybranch-backup

首先,签出P(要拆分的地方之前的提交),并创建一个新的分支来处理

git checkout P
git checkout -b mybranch-splitting

现在,从Q中签出您想要的任何文件,并根据需要进行编辑,以创建新的中间提交:

git checkout Q file1.txt file2.txt
[…edit, stage commit with “git add”, etc…]
git commit -m "Refactored the widgets"

请注意此提交的哈希值,如Q1。现在,在Q1的分离HEAD上检查Q的完整状态,提交这个(创建Q'),并将工作分支向上拉:

git checkout Q
git reset --soft Q1
git commit -m "Added unit tests for widgets"
git branch -f mybranch-splitting

您现在在Q'处执行mybranch拆分,它应该具有与Q完全相同的代码状态。现在将原始分支(从Q到Z)重设为:

git rebase --onto HEAD Q mybranch

现在,mybranch应该看起来像…P->Q1–>Q'–>R'–>…Z',正如您所希望的那样。因此,在检查所有工作正常后,可以删除工作分支和备份分支,并(如果合适)将重写的mybranch推到上游。如果它已经被推了,你需要强制推,所有关于强制推的常见警告都适用。

git push --force mybranch
git branch -d mybranch-splitting mybranch-backup

git rebase-我会做的。

首先,从一个干净的工作目录开始:git状态应该显示没有挂起的修改、删除或添加。

现在,您必须决定要拆分哪些提交。

A) 拆分最近的提交

要拆分最近的提交,首先:

$ git reset HEAD~

现在,以通常的方式单独提交这些片段,根据需要生成任意数量的提交。

B) 将提交拆分到更远的位置

这需要重新定基,即重写历史。要指定正确的提交,您有几个选项:

如果是三次提交,那么$git rebase-i头~3其中3是返回的提交数。如果它在树上比你想数的更远,那么$git rebase-i 123abcd~其中123abcd是要拆分的提交的SHA1。如果您位于要合并到主节点的其他分支(例如,要素分支)上:$git rebase-i主

当您获得rebase编辑屏幕时,找到您想要拆分的提交。在该行的开头,用edit(简称e)替换pick。保存缓冲区并退出。在您要编辑的提交之后,回扣将立即停止。然后:

$ git reset HEAD~

以通常的方式单独提交各个部分,根据需要生成多个提交。

最后

$ git rebase --continue

在没有交互式重新基础的情况下,最容易做的事情是(可能)在要拆分的分支之前创建一个新的分支,然后在提交、重置、隐藏、提交文件移动、重新应用隐藏并提交更改,然后与前一个分支合并,或者在随后的提交中进行樱桃选择。(然后将以前的分支机构名称改为现在的负责人。)(也许最好遵循MBO的建议,并进行交互式重组。)

这已经过去8年多了,但也许有人会发现它对你有所帮助。我能够做到这一点,而不需要重新启动。其目的是将git引导到与git提交之前相同的状态:

# first rewind back (mind the dot,
# though it can be any valid path,
# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit> .

# apply the changes
git checkout <commit-you-want-to-split>

# we're almost there, but the changes are in the index at the moment,
# hence one more step (exactly as git gently suggests):
# (use "git reset HEAD <file>..." to unstage)
git reset

在此之后,您将看到重置后的这些闪亮的未分级更改:并且您的回购处于一种即将提交所有这些文件的状态。从现在起,你可以像往常一样轻松地再次提交。希望这会有所帮助。

使用git-rebase--interactive编辑先前的提交,运行git-resetHEAD~,然后git-add-p添加一些,然后进行提交,然后再添加一些,再进行另一次提交,次数尽可能多。完成后,运行git rebase--continue,您将在堆栈中更早地获得所有拆分提交。

重要提示:请注意,您可以四处游玩并进行所有所需的更改,而不必担心丢失旧的更改,因为您可以始终运行git reflog来找到项目中包含所需更改的点(我们称之为a8c4ab),然后git重置a8c4aa。

下面是一系列命令来说明它的工作原理:

mkdir git测试;cd git测试;初始化

现在添加文件a

vi A

添加此行:

one

gitcommit-我是一个

然后将此行添加到A:

two

gitcommit-am二

然后将此行添加到A:

gitcommit-am三

现在文件A看起来像这样:

one
two
three

我们的git日志如下所示(好吧,我使用的是git log--prett=oneline--prett=“%h%cn%cr----%s”

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

假设我们想将第二次提交分成两份。

git-rebase--交互式HEAD~2

这将显示如下消息:

pick 2b613bc two
pick bfb8e46 three

将第一个pick更改为e以编辑提交。

git重置HEAD~

gitdiff告诉我们,我们刚刚取消了第二次提交的提交:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

让我们进行更改,并在文件a中的行中添加“和第三个”。

git添加。

这通常是在交互式rebase期间,我们将运行gitrebase--continue,因为我们通常只想回到提交堆栈中编辑先前的提交。但这一次,我们希望创建一个新的提交。所以我们将运行gitcommit-am“二加三”。现在我们编辑文件A,并添加第二行和第三行。

git添加。gitcommit-am“二分之二”git rebase—继续

我们的承诺有冲突,三,所以让我们解决它:

我们会改变的

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

to

one
two and a third
two and two thirds
three

git添加。;git rebase—继续

现在我们的gitlog-p看起来像这样:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one