如果不创建分支并在新分支上进行大量时髦的工作,是否有可能在将单个提交提交到本地存储库后将其分成几个不同的提交?
git autorebase split COMMIT_ID
git reset HEAD~
,git stash
,然后git cherry-pick
第一个南瓜内提交,然后git stash pop
。我摘樱桃的情况是相当具体的在这里,但git stash
并git stash pop
是对别人很方便。
如果不创建分支并在新分支上进行大量时髦的工作,是否有可能在将单个提交提交到本地存储库后将其分成几个不同的提交?
git autorebase split COMMIT_ID
git reset HEAD~
,git stash
,然后git cherry-pick
第一个南瓜内提交,然后git stash pop
。我摘樱桃的情况是相当具体的在这里,但git stash
并git stash pop
是对别人很方便。
Answers:
git rebase -i
会做的。
首先,从一个干净的工作目录开始:git status
不应显示任何挂起的修改,删除或添加。
现在,您必须确定要拆分的提交。
要拆分最近的提交,请首先:
$ git reset HEAD~
现在,以通常的方式分别提交片段,产生所需数量的提交。
这需要重新定基础,即重写历史记录。要找到正确的提交,您有几种选择:
如果是三次提交,那么
$ git rebase -i HEAD~3
哪里3
有多少个提交。
如果它在树中的距离比您想计算的要远,则
$ git rebase -i 123abcd~
123abcd
您要拆分的提交的SHA1 在哪里。
如果您打算合并到母版中的其他分支(例如要素分支)上:
$ git rebase -i master
当您获得rebase编辑屏幕时,找到您想要分解的提交。在该行的开头,pick
用edit
(e
简称)替换。保存缓冲区并退出。Rebase现在将在您要编辑的提交之后停止。然后:
$ git reset HEAD~
以通常的方式分别提交片段,生成所需数量的提交,然后
$ git rebase --continue
git rebase --continue
,其实我不得不git add (files to be added)
,git commit
,则git stash
(对于剩余的文件)。之后git rebase --continue
,我习惯git checkout stash .
了获取剩余文件
git add -p
仅添加文件的部分区域的优势,可能还可以e
选择编辑差异以仅提交一些块。git stash
如果您希望继续进行一些工作,但又将其从当前提交中删除,则该功能也很有用。
git rebase -i HEAD^3
命令分别重新排序。这样,如果拆分变坏,您不必撤消太多工作。
git reset HEAD~
。他们没有迷路。
从git-rebase手册(分割提交部分)
在交互模式下,您可以使用操作“ edit”标记提交。但是,这并不一定意味着git rebase希望此编辑的结果恰好是一次提交。实际上,您可以撤消提交,也可以添加其他提交。这可用于将提交分为两部分:
使用开始一个交互式的变基
git rebase -i <commit>^
,<commit>
您想拆分的提交在哪里。实际上,任何提交范围都可以,只要它包含该提交即可。用操作“ edit”标记要拆分的提交。
关于编辑该提交,请执行
git reset HEAD^
。结果是HEAD倒退了一个,索引也随之变化。但是,工作树保持不变。现在,将更改添加到您希望在第一次提交中拥有的索引。您可以使用
git add
(可能以交互方式)或git gui
(或同时使用两者)来做到这一点。使用现在合适的提交消息来提交当前索引。
重复最后两个步骤,直到工作树干净为止。
继续进行基础调整
git rebase --continue
。
~
而不是^
。
reset
毕竟,我们正在提交(包括消息)。如果您知道要拆分一个提交但想保留部分/全部消息,则明智的做法是获取该消息的副本。因此,git show
提交之前rebase
,或者如果您忘记或喜欢此提交:稍后通过进行恢复reflog
。直到两周之内将其垃圾收集起来,否则任何东西都不会被“丢失”。
~
和^
是不同的东西,甚至在Windows上。您仍然需要插入符号^
,因此只需要根据自己的外壳对其进行转义即可。在PowerShell中,它是HEAD`^
。使用cmd.exe,您可以将其加倍以像一样进行转义HEAD^^
。在大多数(全部?)shell中,您可以使用诸如的引号引起来"HEAD^"
。
git commit --reuse-message=abcd123
。它的简短选择是-C
。
使用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
让我们分阶段进行更改,然后在file的该行中添加“第三个” A
。
git add .
这通常是我们在交互式基础库中将要运行的地方git rebase --continue
,因为我们通常只想返回到提交堆栈中以编辑较早的提交。但是这次,我们要创建一个新的提交。这样我们就出发了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 -i
来编辑要拆分的提交并将其部分提交。
将文件拆分为不同的提交时,这种方法效果很好,但是如果您希望将各个文件的更改分开,则需要了解更多信息。
到达要拆分的提交,使用rebase -i
并将其标记为edit
,您有两个选择。
使用完后,使用分别git reset HEAD~
浏览补丁git add -p
以选择每次提交中所需的补丁
编辑工作副本以删除不需要的更改;提交临时状态;然后拉回完整提交以进行下一轮。
如果要分割大型提交,选项2很有用,因为它使您可以检查过渡版本在合并过程中是否正确构建和运行。这进行如下。
使用rebase -i
并edit
提交后,使用
git reset --soft HEAD~
撤消提交,但将提交的文件保留在索引中。您还可以通过省略--soft来进行混合重置,具体取决于您的初次提交将接近最终结果。唯一的区别是,是先进行所有已分阶段的更改,还是先进行所有未分阶段的更改。
现在进入编辑代码。您可以删除更改,删除添加的文件以及执行想要构造的所有提交的所有操作。您还可以构建,运行它,并确认您拥有一致的源集。
满意后,请根据需要暂存/取消暂存文件(我喜欢为此使用git gui
),然后通过UI或命令行提交更改
git commit
那是第一次完成。现在,您想将工作副本还原为拆分提交后的状态,以便您可以在下一次提交时进行更多更改。要查找正在编辑的提交的sha1,请使用git status
。在状态的前几行中,您将看到当前正在执行的rebase命令,在其中您可以找到原始提交的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
提交和文件位置的形式检出该提交的内容。在这里,我.
用作替换整个工作副本的文件位置:
git checkout 65dfb6a .
不要错过最后的点!
这将签出并暂存文件,并按照您正在编辑的提交后的状态进行登台,但相对于您之前所做的提交,因此,您已经提交的所有更改将不属于提交。
您可以立即进行并按原样提交以完成拆分,也可以再次进行,删除提交的某些部分,然后再进行一次临时提交。
如果您想将原始提交消息重用于一个或多个提交,则可以直接从rebase的工作文件中使用它:
git commit --file .git/rebase-merge/message
最后,一旦您完成所有更改,
git rebase --continue
将进行并完成变基操作。
git checkout *Sha I'm Editing* .
总是说Updated 0 paths from *Some Sha That's Not In Git Log*
并且不做任何更改。
git rebase --interactive
可用于将提交拆分为较小的提交。Rebase上的Git文档对该过程进行了简要的演练-拆分提交:
在交互模式下,您可以使用操作“ edit”标记提交。但是,这并不一定意味着
git rebase
期望此编辑的结果恰好是一次提交。实际上,您可以撤消提交,也可以添加其他提交。这可用于将提交分为两部分:
使用开始一个交互式的变基
git rebase -i <commit>^
,<commit>
您想拆分的提交在哪里。实际上,任何提交范围都可以,只要它包含该提交即可。用操作“ edit”标记要拆分的提交。
关于编辑该提交,请执行
git reset HEAD^
。结果是HEAD倒退了一个,索引也随之变化。但是,工作树保持不变。现在,将更改添加到您希望在第一次提交中拥有的索引。您可以使用
git add
(可能是交互方式)或git gui(或两者都使用)来做到这一点。使用现在合适的提交消息来提交当前索引。
重复最后两个步骤,直到工作树干净为止。
继续进行基础调整
git rebase --continue
。如果您不确定中间版本是否一致(它们可以编译,通过测试套件等),则应该
git stash
在每次提交,测试和修正必要的修改后,将尚未提交的更改保存起来。 。
^
是命令行的转义符:应将其加倍。例如,发出git reset HEAD^^
而不是git reset HEAD^
。
^
两次重置当前HEAD上方的两次提交。
"HEAD^"
在cmd.exe或PowerShell中,HEAD^^
在cmd.exe中,HEAD`^
在PowerShell中。了解外壳(以及您的特定外壳)如何工作(即命令如何变成传递到程序的各个部分)很有用,以便您可以在线调整命令以适应特定外壳的正确字符。(不特定于Windows。)
现在,在Windows上最新的TortoiseGit中,您可以轻松完成此操作。
打开变基对话框,对其进行配置,然后执行以下步骤。
Edit
”(在选择,压缩,删除...中)。 Start
”开始重新设定基准。 Edit/Split
”按钮并Amend
直接单击“ ”。提交对话框打开。commit
”。 非常有帮助,谢谢TortoiseGit!
没有交互性基准库,最简单的操作是(可能)在要拆分的分支之前先提交一个新分支,即执行Cherry-pick -n提交,重置,存储,提交文件移动,重新应用存储和提交更改,然后与以前的分支合并,或者选择后续的提交。(然后将以前的分支名称更改为当前的头。)(最好遵循MBO的建议并进行交互式的基准调整。)
rebase -i
建议要容易得多。我认为由于缺少任何格式,因此没有引起足够的重视。既然您现在拥有126k积分,并且可能知道该怎么做,也许您可以进行复习。;)
我认为这是我使用的最好方法git rebase -i
。我创建了一个视频来展示拆分提交的步骤: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
创建第一次提交(C):
git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"
创建第二个提交(D):
git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"
已经超过8年了,但是也许有人会发现它对您有所帮助。没有我我就能做到了rebase -i
。这个想法是使git达到您之前的状态git commit
:
# 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
在此之后,您将看到此光泽,Unstaged changes after reset:
并且您的存储库处于将要提交所有这些文件的状态。从现在开始,您可以像平时一样轻松地再次提交它。希望能帮助到你。
必要命令的快速参考,因为我基本上知道该怎么做,但总是忘记正确的语法:
git rebase -i <sha1_before_split>
# mark the targeted commit with 'edit'
git reset HEAD^
git add ...
git commit -m "First part"
git add ...
git commit -m "Second part"
git rebase --continue