英文:
Git combine all commits between two commits using their hashes
问题
在给定的 git 分支上,
-- c1 ---- c2 ------ HEAD
我想将 c1
和 c2
以及它们之间的所有内容合并成一个提交。
要求:
- 我知道
c1
和c2
的哈希值,但不知道它们相对于HEAD
的位置。 - 我想以编程方式执行此操作(在脚本中调用),因此无法使用交互模式。
我知道这个问题已经被多次提出,但我找不到任何现有的答案能够满足这些要求。
英文:
Given this git branch,
-- c1 ---- c2 ------ HEAD
I want to combine c1
and c2
and everything in between into one commit.
Requirements:
- I know
c1
andc2
hashes, but not their relative positions toHEAD
. - I want to do this programmatically (call it in a script), so I cannot use interactive mode.
I know this question has been asked several times, but I cannot find any existing answer that satisfies those requirements.
答案1
得分: 2
这将完成它(将您所在的分支称为 originalBranch
):
git switch --det c2
git switch -c temp
git reset --soft c1
git commit -msquash
git rebase --onto temp c2 originalBranch
git branch -D temp
思路如下:
- 我们回到了
c2
,在那里创建了一个名为temp
的分支,以便以后可以找到它。 - 然后,我们从
c2
一直压缩到c1
(包括c1
)——这是软重置后紧接着的提交;这是一种类型 1 的后悔。现在,名称temp
指向这个新的单一压缩提交。 - 最后,我们返回到原始的 HEAD(我称之为
originalBranch
)并将所有从旧的c2
开始的提交移动到新的单一压缩提交上,这个提交(如我之前所说)由名称temp
指向。 - 我们的工作现在已经完成,但是我们不再需要分支名称
temp
,所以我们将其删除。
所以我们现在从这个状态:
A -- B -- C1 -- ? -- ? -- C2 -- D -- E -- F <- originalBranch
到这个状态:
A -- B -- C1 -- squash -- D' -- E' -- F' <- originalBranch
\
-- ? -- ? -- C2 -- D -- E -- F
从我的图表中可以看出,旧的提交仍然存在,但由于没有名称再指向它们,它们将在下一次垃圾回收期间全部清除。
英文:
This would do it (call the branch you are on originalBranch
):
git switch --det c2
git switch -c temp
git reset --soft c1
git commit -msquash
git rebase --onto temp c2 originalBranch
git branch -D temp
The idea is this:
- We get ourselves back at
c2
and plant a branch nametemp
there, so that we can find it again. - We then squash from
c2
all the way back toc1
inclusive — that's the soft reset followed by a commit; this is a type 1 regret. The nametemp
now points to this new single squash commit. - Finally, we return to whatever was the original HEAD (which I have named
originalBranch
) and move all the commits starting at (but not including) the oldc2
onto the new single squash commit, which (as I have already said) is pointed to by the nametemp
. - Our work is now done, but we no longer need the branch name
temp
for anything, so we delete it.
So we have now gone from this:
A -- B -- C1 -- ? -- ? -- C2 -- D -- E -- F <- originalBranch
To this:
A -- B -- C1 -- squash -- D' -- E' -- F' <- originalBranch
\
-- ? -- ? -- C2 -- D -- E -- F
The old commits, as you can see from my diagram, still exist, but they will all be mopped up during the next garbage collection because no name points to them any longer.
答案2
得分: 0
我不认为有任何可以直接完成这个任务的工具,但可以编写脚本来实现。
伪代码:
- 检出
c1^
- 进行
c2
的压缩合并并提交结果 - 将
c2..HEAD
樱桃挑选到结果上
可能的问题:
- 如果在
c1^
和HEAD
之间存在任何合并提交,挑选c2..HEAD
将会导致混乱。
英文:
I don't think there is any tool that does this out of the box, but it can be scripted.
Pseudo code:
- checkout
c1^
- do a squash-merge of
c2
and commit the results - cherry pick
c2..HEAD
onto the results
Potential problem:
- if there were any merge commits between
c1^
andHEAD
, cherry pickingc2..HEAD
will create a mess.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论