将以前的提交分成多个提交
如果不创build一个分支并在一个新的分支上进行一些时髦的工作,在一个提交被提交到本地存储库后,是否有可能将一个提交分成几个不同的提交?
git rebase -i
会做到这一点。
要拆分最近的提交,首先:
$ git reset HEAD~
现在按通常的方式分别执行这些部分,根据需要生成尽可能多的提交。
那么,如果它在树的后面
$ git rebase -i HEAD~3
其中3
是多less提交它是。
那么,如果它在树的后面比你想要数的更远
$ git rebase -i 123abcd^
其中123abcd
是要分离的提交的SHA1。
当你得到分配编辑屏幕时,find你想分离的提交。 在该行的开始处,将pick
replace为edit
(简称e
)。 保存缓冲区并退出。 现在,Rebase将在您要编辑的提交之后停止。 然后:
$ git reset HEAD~
然后以通常的方式单独提交这些作品,然后根据需要生成尽可能多的提交
$ git rebase --continue
从git-rebase手册(SPLITTING COMMITS部分)
在交互模式下,您可以使用“编辑”操作标记提交。 但是,这并不一定意味着git rebase期望这个编辑的结果只是一个提交。 事实上,您可以撤销提交,也可以添加其他提交。 这可以用来将一个提交分成两部分:
用
git rebase -i <commit>^
开始一个交互式rebase,其中<commit>
是你想要分割的提交。 实际上,只要包含该提交,任何提交范围都会执行。使用“编辑”操作标记要分割的提交。
当编辑提交时,执行
git reset HEAD^
。 其效果是HEAD被倒回一个,索引也是如此。 但是,工作树保持不变。现在将更改添加到您想要在第一次提交中使用的索引中。 你可以使用
git add
(可能交互式地)或者git gui
(或者两者)来做到这一点。用现在提交的任何提交消息来提交当前的索引。
重复最后两个步骤,直到你的工作树干净。
用
git rebase --continue
继续rebase – 继续。
使用git rebase --interactive
编辑早期的提交,运行git reset HEAD~
,然后用git add -p
添加一些,然后进行提交,然后再添加一些提交,然后再进行一次提交,只要你喜欢。 当你完成后,运行git rebase --continue
,你将在堆栈中提前完成所有的分离提交。
重要提示 :请注意,您可以四处游戏并进行所有您想要的更改,而不必担心丢失旧的更改,因为您始终可以运行git reflog
来查找项目中包含所需更改的点(让我们打电话它a8c4ab
),然后git reset a8c4ab
。
这里有一系列命令来显示它是如何工作的:
mkdir git-test; cd git-test; git init
现在添加一个文件A
vi A
添加这一行:
one
git commit -am one
然后将此行添加到A:
two
git commit -am two
然后将此行添加到A:
three
git commit -am three
现在文件A看起来像这样:
one two three
和我们的git log
如下所示(好吧,我使用git log --pretty=oneline --pretty="%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
假设我们想分割第二个提交, two
。
git rebase --interactive HEAD~2
这会产生一个如下所示的消息:
pick 2b613bc two pick bfb8e46 three
将第一个pick
改为e
以编辑该提交。
git reset HEAD~
git diff
告诉我们,我们刚刚取消了我们为第二次提交所做的提交:
diff --git a/A b/A index 5626abf..814f4a4 100644 --- a/A +++ b/A @@ -1 +1,2 @@ one +two
让我们把这个改变,并在文件A
添加“和第三”到该行。
git add .
这通常是交互式rebase中的一个地方,我们将运行git rebase --continue
,因为我们通常只想回到我们的提交栈来编辑早期的提交。 但是这一次,我们要创build一个新的提交。 所以我们将运行git commit -am 'two and a third'
。 现在我们编辑文件A
并添加行two and two thirds
。
git add .
git commit -am 'two and two thirds'
git rebase --continue
我们与我们的承诺有冲突, three
,让我们来解决它:
我们会改变的
one <<<<<<< HEAD two and a third two and two thirds ======= two three >>>>>>> bfb8e46... three
至
one two and a third two and two thirds three
git add .; git rebase --continue
现在我们的git log -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
git rebase --interactive
可以用来将提交拆分成更小的提交。 关于rebase的Git文档有一个简明的stream程演示 – 分裂提交 :
在交互模式下,您可以使用“编辑”操作标记提交。 但是,这并不一定意味着
git rebase
期望这个编辑的结果只是一个提交。 事实上,您可以撤销提交,也可以添加其他提交。 这可以用来将一个提交分成两部分:
用
git rebase -i <commit>^
开始一个交互式rebase,其中<commit>
是你想要分割的提交。 实际上,只要包含该提交,任何提交范围都会执行。使用“编辑”操作标记要分割的提交。
当编辑提交时,执行
git reset HEAD^
。 其效果是HEAD被倒回一个,索引也是如此。 但是,工作树保持不变。现在将更改添加到您想要在第一次提交中使用的索引中。 你可以使用
git add
(可能交互式地)或者git gui(或者两者)来做到这一点。用现在提交的任何提交消息来提交当前的索引。
重复最后两个步骤,直到你的工作树干净。
用
git rebase --continue
继续rebase – 继续。如果你不确定中间修订是否一致(它们编译,通过testing套件等),你应该使用
git stash
来在每次提交,testing和修改提交(如果修复)之后将尚未提交的更改存储起来是必要的。
你可以做互动rebase git rebase -i
。 手册页正是你想要的:
请注意,还有git reset --soft HEAD^
。 它类似于git reset
(默认为--mixed
),但是它保留了索引内容。 所以,如果你已经添加/删除文件,你已经在索引中。
在巨大的承诺的情况下变得非常有用。
以前的答案已经覆盖了使用git rebase -i
来编辑你想要分割的提交,并在部分提交。
当将文件拆分成不同的提交时,这种方式很好,但是如果要分开更改单个文件,还需要了解更多内容。
有了你想要分裂的提交,使用rebase -i
并将其标记为edit
,你有两个select。
-
使用
git reset HEAD~
之后,使用git add -p
分别select你想要的补丁 -
编辑工作副本以删除不需要的更改; 犯下过渡状态; 然后再撤回下一轮的全部承诺。
如果您正在拆分大型提交,则选项2非常有用,因为它可以让您检查临时版本是否作为合并的一部分进行构build和正确运行。 这进行如下。
使用rebase -i
并edit
提交后,使用
git reset --soft HEAD~
撤销提交,但将提交的文件留在索引中。 您也可以通过省略–soft来进行混合重置,具体取决于您最初的提交将会如何接近最终结果。 唯一的区别是你是从所有的变化开始还是全部变成未分阶段的。
现在进入并编辑代码。 您可以删除更改,删除添加的文件,并执行任何您想要构build您正在查找的系列的第一个提交。 您也可以构build它,运行它,并确认您拥有一组一致的源代码。
一旦你快乐,根据需要放置/取消文件的放置(我喜欢使用git gui
),并通过UI或命令行提交更改
git commit
这是第一次提交。 现在,您要将工作副本恢复到您分裂后的提交状态,以便您可以为下一次提交进行更多更改。 要find正在编辑的提交的sha1,请使用git status
。 在状态的前几行中,您将看到当前正在执行的rebase命令,您可以在其中find原始提交的sha1:
$ git status interactive rebase in progress; onto be83b41 Last commands done (3 commands done): pick 4847406 US135756: add debugging to the file download code e 65dfb6a US135756: write data and download from remote (see more in file .git/rebase-merge/done) ...
在这种情况下,我正在编辑的提交sha1 65dfb6a
。 知道这一点,我可以使用git checkout
的forms来git checkout
我的工作目录上的提交内容,它同时提交一个提交和一个文件位置。 我在这里使用.
作为replace整个工作副本的文件位置:
git checkout 65dfb6a .
不要错过最后的点!
这将检查并分阶段执行你正在编辑的提交之后的文件,但相对于你之前的提交,所以你已经提交的任何改变将不会是提交的一部分。
现在可以继续进行,直接完成拆分,或者再次执行,在进行另一个临时提交之前删除提交的某些部分。
如果你想重用一个或多个提交的原始提交信息,你可以直接从rebase的工作文件中使用它:
git commit --file .git/rebase-merge/message
最后,一旦你做了所有的改变,
git rebase --continue
将继续并完成重组工作。
现在在Windows上最新的TortoiseGit,你可以很容易地做到这一点。
打开rebase对话框,进行configuration ,然后执行以下步骤。
- 右键单击要分割的提交,然后select“
Edit
”(在选取,压扁,删除…之间)。 - 点击“
Start
”开始rebasing。 - 一旦到达提交分裂,检查“
Edit/Split
”button,并直接点击“Amend
”。 提交对话框打开。
- 取消select要放在单独提交中的文件。
- 编辑提交消息,然后单击“
commit
”。 - 在提交文件之前,提交对话框将一次又一次地打开。 当没有更多的文件提交,它仍然会问你是否要添加一个提交。
非常有帮助,谢谢TortoiseGit!
最简单的事情是没有交互式rebase(可能是)在提交之前创build一个新的分支,然后select提交,重置,隐藏,提交文件移动,重新应用存储提交更改,然后与前一个分支合并,或者select后面的提交。 (然后把前面的分支名称改为当前的头)。(最好遵循MBO的build议,并做一个交互式分配。)
我认为这是我使用git rebase -i
的最好方法。 我创build了一个video来显示拆分提交的步骤: https : //www.youtube.com/watch?v = 3EzOz7e1ADI
如果你有这个:
A - B <- mybranch
在提交B中提交了一些内容的地方:
/modules/a/file1 /modules/a/file2 /modules/b/file3 /modules/b/file4
但是你想把B分解成C – D,并得到这个结果:
A - C - D <-mybranch
你可以像这样分割内容(不同目录中的内容在不同的提交中)…
将分支重置回分割之前的提交:
git checkout mybranch git reset --hard A
创build第一个提交(C):
git checkout B /modules/a git add -u git commit -m "content of /modules/a"
创build第二个提交(D):
git checkout B /modules/b git add -u git commit -m "content of /modules/b"