我目前正在从事一个使用 SVN 作为存储库的项目。在本地,我对不想提交到存储库的代码进行了几次“实验”。因此,我在 SVN 工作目录之上本地使用 git,并使用多个分支进行不同的“实验”。所以它看起来例如像这样。
C0 ---- C7 (master)
\
\---- C1 ---- C2 ---- C4 (exp1)
\ \ \
\ \ \---- C3 (exp2)
\ \
\ \---- C5 (exp3)
\
\---- C6 (exp4)
在分支上
master
我想要未受污染的 SVN 存储库,即 C0 是 SVN 存储库修订版 x,C7 是 SVN 存储库修订版 x + n。
是否可以轻松地将所有
exp
分支一次性重新设置到 C7 上,使得树如下图所示?
C0 ---- C7 (master)
\
\---- C1' ---- C2' ---- C4' (exp1)
\ \ \
\ \ \---- C3' (exp2)
\ \
\ \---- C5' (exp3)
\
\---- C6' (exp4)
我想使用 rebase,因为我不想修改本地 SVN Checkout 的状态,并且希望将我的更改构建在 SVN 修订之上。
我还对在 SourceTree 内工作而无需使用 shell 的解决方案感兴趣。
你无法一步获得这一点。最好的情况是你一根一根地移动每个分支;这将是顺序:
git rebase --onto master exp1
git rebase --onto c2' c2 exp2
git rebase --onto c1' c1 exp3
git rebase --onto master exp4
关键是从旧树中的每个分支点(例如上面的 c2)到新树(例如上面的 c2')进行变基。
我只想提一下,GoZoner 的序列在第一行(和最后一行)有一个错误。
exp1
不是上游,而是你想要变基的分支。
为了启动序列,您需要将 master 作为上游,即
git rebase --onto master master exp1
或短,没有 --onto
则为 git rebase master exp1
。
问题中示例的总正确序列将是:
git rebase master exp1
git rebase --onto c2' c2 exp2
git rebase --onto c1' c1 exp3
git rebase master exp4
您可以通过一个小技巧来重新设置多个分支/树的基础。
--no-ff
合并)- 更新来自 @kdb、@franckspike--preserve-merges
选项添加到您的重新设置命令中git reset --hard [Commit-hash of C4' (exp1)]
这不能直接在 git 中完成,但可以使用 git-assembler 实现自动化。
引用我在https://stackoverflow.com/a/62835799/2792879中的类似答案,这里是指向rebasing本地分支
文档中示例的直接链接自 git v2.44 起,有一个新的实验性功能 git replay 允许使用命令相对轻松地完成此操作(基于您的示例):
git replay --onto C7 C0..exp1 C0..exp2 C0..exp3 C0..exp4 | git update-ref --stdin
甚至还有一个更简单的语法(但我没有成功使用它):
git replay --onto C7 ^C0 exp1 exp2 exp3 exp4 | git update-ref --stdin
备注:
replay
命令不会更新引用,而只是创建 git 对象并在控制台中输出引用更新,需要以适合 git update-ref --stdin
的格式完成,从而有效地进行引用更新。