git相当于hg rebase -s source -d destination?

时间:2016-10-29 22:18:43

标签: git rebase

是否有相当于hg rebase -s source -d newparent的git?

也就是说,'修剪'source处的分支并在newparent处'移植'。或source重新newparent(在适当的情况下合并)。

或者如何从中获取:

A - B - C
 \
  D - E
   \
    F

对此:

A - B - C
     \
      D'- E'
       \
        F'

在这种情况下,sourceDnewparentB。执行hg rebase -s D -d B会产生所需的结果。有没有git等价物?

我已经尝试了git rebase --onto B D但除了移动分支标签外,它显然没有做任何事情。

编辑澄清:目标不是在树中重新提交与上述完全相同的提交。以上就是一个例子。我的目标是让我在任何其他提交之上重新提交一个提交,只要没有像尝试重新提交合并提交或类似的那样奇怪的情况。我创建了几个重新创建上面树的脚本,一个用于hg

#!/bin/sh
set -e
rm -rf .hg
hg init
cat > .hg/hgrc <<'EOF'
[ui]
username = Rebase tester <no@email>
[extensions]
rebase =
EOF
echo A > file.txt
hg add file.txt
hg commit -m A_msg
hg bookmark A_bm
hg bookmark dummy # to stop A from tracking us
echo B > file.txt
hg commit -m B_msg
hg bookmark B_bm
hg bookmark graftpoint
hg bookmark -f dummy
echo C > file.txt
hg commit -m C_msg
hg bookmark C_bm
hg checkout A_bm
hg bookmark -f dummy
echo D > file.txt
hg commit -m D_msg
hg bookmark D_bm
hg bookmark prunepoint
hg bookmark -f dummy
echo E > file.txt
hg commit -m E_msg
hg bookmark E_bm
hg checkout D_bm
hg bookmark -f dummy
echo F > file.txt
hg commit -m F_msg
hg bookmark F_bm
hg bookmark -d dummy
hg log -G -T '{desc} {bookmarks} {rev}:{node|short}'
hg rebase -s D_bm -d B_bm -t internal:other
hg log -G -T '{desc} {bookmarks} {rev}:{node|short}'

和一个git:

#!/bin/sh
set -e
rm -rf .git
git init
git config user.name 'Rebase tester'
git config user.email 'no@email'
echo A > file.txt
git add file.txt
git commit -m A_msg
git branch A_br
echo B > file.txt
git commit -a -m B_msg
git branch B_br
git branch graftpoint
echo C > file.txt
git commit -a -m C_msg
git branch C_br
git checkout A_br
git checkout -b D_br
echo D > file.txt
git commit -a -m D_msg
git branch prunepoint
git checkout -b E_br
echo E > file.txt
git commit -a -m E_msg
git checkout D_br
git checkout -b F_br
echo F > file.txt
git commit -a -m F_msg
git log --graph --all --format=format:'%s %d %h%n'

#insert command(s) here

git log --graph --all --format=format:'%s %d %h%n'

第一个脚本输出的树是:

@  F_msg F_bm 5:5ffe9c283d51
|
| o  E_msg E_bm 4:9f83c609d7b2
|/
o  D_msg D_bm prunepoint 3:c3561e22f394
|
| o  C_msg C_bm 2:e7dd832a739b
| |
| o  B_msg B_bm graftpoint 1:c3d6803dba3e
|/
o  A_msg A_bm 0:f52f4706cef0

@  F_msg F_bm 5:efe4fde4dcdf
|
| o  E_msg E_bm 4:b2402cb25f70
|/
o  D_msg D_bm prunepoint 3:5849595efdde
|
| o  C_msg C_bm 2:e7dd832a739b
|/
o  B_msg B_bm graftpoint 1:c3d6803dba3e
|
o  A_msg A_bm 0:f52f4706cef0

完全符合预期。第二个脚本的输出是

* C_msg  (master, C_br) de97063
|  
* B_msg  (B_br) 6053c6b
|    
| * E_msg  (E_br) 13d4fac
| |     
| | * F_msg  (HEAD, F_br) b9ce3c4
| |/  
| |   
| * D_msg  (D_br) ed2ba19
|/  
|  
* A_msg  (A_br) 2cf9476

(两次)。第二个应该是这样的:

* C_msg  (master, C_br) de97063
|    
| * E_msg  (E_br) 1398dc5
| |     
| | * F_msg  (HEAD, F_br) 8ee34ad
| |/  
| |   
| * D_msg  (D_br) ed873f7
|/  
|  
* B_msg  (B_br) 6053c6b
|  
* A_msg  (A_br) 2cf9476

我的问题是hg rebase -s source -d destination适用于任何情况,但我还没有办法对git做同样的事情。我发现了几个第三方程序,但它们似乎没有解决这个用例。一个是git reparent,另一个是git-reparent-branch。我还发现了一个solution using grafts and filter-branch,但我不清楚这会正确处理冲突。

2 个答案:

答案 0 :(得分:0)

根据torek的回答,在撰写本文时,没有自动化的方法。因此,下一个最好的方法可能是手动重现树。我说&#34;树&#34;因为我不知道如果涉及合并提交将会发生什么。

因此,假设提交修剪形成一个独立的子树,以下应该有效:

  • 查找修剪提交的所有下游提示(例如,使用gitk --all)。
  • 查看嫁接点。
  • 运行git rebase --onto HEAD HEAD tip1
  • 对子树中的每个分裂点(分支点,即具有两个或更多子节点的提交,可能包括原始分裂点)重复。
  • 修复非提示的引用(如果有)。

在示例中就是这样做的:

git checkout graftpoint
set +e
git rebase --onto HEAD HEAD E_br
  # Known conflict
  echo D > file.txt
  git add file.txt
  git rebase --continue
set -e
# Repeat for the branching point at E_br~1
git checkout E_br~1
git branch -f prunepoint # fix this reference while we're here
git branch -f D_br # fix this reference while we're here
git rebase --onto HEAD HEAD F_br

这会生成所需的图表:

* C_msg  (master, C_br) 612ba5c
|    
| * E_msg  (E_br) 1b4fb2e
| |     
| | * F_msg  (HEAD, F_br) 78d5a1f
| |/  
| |   
| * D_msg  (prunepoint, D_br) c4975c0
|/  
|  
* B_msg  (graftpoint, B_br) cc630ea
|  
* A_msg  (A_br) 01084ac

A_brB_brC_br的哈希值当然与操作前的树中的哈希值相同,这与问题中的不同,因为树是重新生成的-created)。

答案 1 :(得分:0)

为什么会这么复杂?

git rebase --onto B A D
git rebase --onto D D@{1} E   # or ... "--onto D{,@{1}} E" in bash
git rebase --onto D D@{1} F   # or ... "--onto D{,@{1}} F" in bash

应该做的工作(以模数解决任何合并冲突)。

我经常这样做,因为我编写了一个自动执行此操作的脚本。遗憾的是,Git并没有为用户提供这样的工具,而是让他们自己编写,但是Git中的概念没有任何内在的错误可以防止这种情况发生。 Git中的概念与Mercurial中的概念完全不同。