Git:在频繁移动的基础上维护许多主题分支

问题描述 投票:0回答:4

在我的日常 git 工作流程中,我有很多主题分支,如下所示:

 o--o--o (t2)
             /
         o--o (t1)
        /
 哦——哦——哦(大师)
        \
         哦--哦--o (t3)

当我从上游拉动时,

 o--o--o (t2)
             /
         o--o (t1)
        /
 o--o--o--n--n--n(主)
        \
         哦--哦--o (t3)

我想rebase我所有的主题分支都在新的master之上:

 o'--o'--o' (t2)
                       /
                  o'--o' (t1)
                 /
 o--o--o--n--n--n(主)
                 \
                  哦——哦——哦(t3)

目前我使用

git rebase --onto
手动完成此操作。在这种情况下,整个更新过程将是:

$ git checkout master
$ git pull
$ git rebase master t1
$ git rebase --onto t1 t2~3 t2
$ git rebase master t3

在各个主题分支之间跳转并添加提交时,这会变得更加棘手。

在我的例子中,主题分支之间的依赖关系纯粹是树状的:没有分支依赖于多个其他分支。 (我最终必须以某种特定的顺序上游依赖补丁,所以我先验地选择该顺序。)

有什么工具可以帮助我管理这个工作流程吗?我见过 TopGit,但它似乎与

tg patch
基于电子邮件的工作流程密切相关,这与我无关。

git
4个回答
10
投票

git 邮件列表上也提出了几乎相同的问题: 同时变基多个分支... 链接的响应附加了一个 perl 脚本,可生成您需要的命令。

如果您希望此脚本快速运行并避免让它踩到您的脚趾,还可以考虑使用

git-new-workdir
来设置仅用于自动变基的工作副本。

如果您发现自己一遍又一遍地解决相同的冲突,请考虑启用 git rerere

话虽如此,这里有一个替代食谱:

# Construct a placeholder commit that has all topics as parent.
HEADS="$(git for-each-ref refs/heads/\*)" &&
MAGIC_COMMIT=$(echo "Magic Octopus"$'\n\n'"$HEADS" |
  git commit-tree \
    $(git merge-base $(echo "$HEADS" | sed 's/ .*//' ))^{tree} \
    $(echo "$HEADS" | sed 's/ .*//;s/^/-p /')) &&
git update-ref refs/hidden/all $MAGIC_COMMIT

# Rebase the whole lot at once.
git rebase --preserve-merges master refs/hidden/all

# Resolve conflicts and all that jazz.

# Update topic refs from the rebased placeholder.
PARENT=
echo "$HEADS" |
while read HASH TYPE REF
do
  let ++PARENT
  git update-ref -m 'Mass rebase' "$REF" refs/hidden/all^$PARENT "$HASH"
done

0
投票

有一个新工具可以自动执行此类任务:git-assembler

这是指向文档中示例的直接链接,用于 rebase 本地分支

不过,您不应该立即解雇 TopGit。生成电子邮件补丁的能力完全是可选的。


0
投票

自 git v2.44 起,有一个新的实验性命令 git replay 允许使用该命令相对轻松地完成此操作(基于您的示例):

git replay --onto master old_master..t1 old_master..t2 old_master..t3 | git update-ref --stdin

甚至还有一种更简单的语法,其中提交范围的表达方式不同:

git replay --onto master ^old_master t1 t2 t3 | git update-ref --stdin

备注:

  • 该命令不使用工作目录来操作
  • 因此目前无法处理冲突(即如果遇到冲突并返回不同于 0 的退出代码,则不执行任何操作)
  • 如果已应用提交,则正在创建空提交
  • replay
    命令不会更新引用,而只是创建 git 对象并在控制台中输出引用更新,需要以适合
    git update-ref --stdin
    的格式完成,从而有效地进行引用更新。
  • 如果检出重播的一个分支,则可能需要同步工作目录。因此,最好有一个干净的工作目录或从另一个签出的分支启动它。

-4
投票

不要变基。从一个共同点开始你的功能。合并最终会减少工作量。

这就是我们所做的:

http://dymitruk.com/blog/2012/02/05/branch-per-feature/

© www.soinside.com 2019 - 2024. All rights reserved.