Git - 进一步向下徘徊 [英] Git - remerging further down the line
问题描述
Master A\ - B - C\ - D\ --- ------ E
Branch l - m --- n --- o - p - q
这里n是一个合并,我们必须解决大量的冲突,我们希望避免再次解决。我们希望在不创建新的合并提交的情况下将E合并回来。所以我们回到o合并E并在顶部选择p和q:
Master A\ - B - C\ - D\ -------- E\
Branch l - m --- n\ - o - p - q \
Tmp ------------- o'-pq
如果这个工作没有错误,我们可以删除旧的分支。
如果我是第一个想到这种工作流程的人,我会感到惊讶。有没有可以自动执行此操作的任何git扩展?
我已经开始编写脚本来执行此操作,但主要问题是选择o。 :/ ^合并 - 在大多数情况下会选择o,但如果没有更好的方法避免依赖不是以合并单词开始的提交消息,将会感到惊讶。 要追溯启用rerere,请参阅此处。在这个答案中的脚本不会变成rerere,并且在 o
中的冲突问题。 rerere
执行 n ... E
合并并应用任何 n ... D
>仍然有效的解决方案,而此脚本执行标准 o ... E
合并(但替换父< o
复制图形以供参考: / em>
之前需要之后
主A \ - B - C\ - D \\ \\ .... E \主A \ - B - C \ - D ... E \
分支l - m --- n --- o - p-- q / Branch l - m --- n ------ o' - p' - q'
rerere将因此绕过 E
-reverted n ... D
冲突,while该剧本将把复归视为进一步的变化。这两个脚本都生成了上图中的期望之后图,但是它们通过不同的路线到达那里。
一个小时的尝试没有产生任何更多
我不清楚rerere或脚本的行为 b 当我做的时候 返回o,合并E 加上 用 所以完整的程序是, 你可以改变(从 在一个子框架中,退出并继续执行,不会有任何麻烦,你可以通过这样做来减少它的脆弱性。 编辑:更新来处理更新合并时没有任何樱桃挑选。 The main disadvantage of merging vs. rebasing is that merging results in a messy tree. If the master is frequently being updated, then merging in mastery every time there has been a significant update will create a whole host of unnecessary commits. Now, most of the time, there isn't actually any need for this. Consider the repository as follows: Here n is a merge where we had to resolve a significant amount of conflicts which we want to avoid resolving again. We want to merge E back in without creating a new merge commit So we go back to o, merge E and cherry-pick p and q on top: If this works without an error, we can then remove the old branch. I would be surprised if I was the first person to think of this kind of workflow. Are there any git extensions that can automate this? I've started working on a script to do this, but the main issue is selecting o. ":/^Merge" - will select o in most cases, but it would be surprised if there wasn't a better way that avoids relying on commit messages not starting with the word Merge. edit: To retroactively enable rerere, see here.. The script in this answer doesn't turn rerere on and will behave differently than rerere would in the presence of further changes, in Copying the graph for reference: rerere will thus bypass An hour's trying hasn't produced any more comprehensible further textual description of the differences than simply looking at the graphs and deducing. It's not clear to me that either rerere's or the script's behavior is always better. When I do go back to o, merge E with I get with So the complete procedure is, If you're willing to lose any conflict resolutions done in If doing work in a subshell and exiting from that to continue isn't any trouble you can make this much less fragile by doing edit: update to handle updating the merge when there's nothing to cherry-pick. 这篇关于Git - 进一步向下徘徊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
blockquote>
git checkout o
git merge E
Master A\ - B - C\ - D\ ---- ----- E
分支l - m --- n --- o \ -p - q \
HEAD`-------- o'
o
用于 o '
的父母。您确实需要 o'
内容(以保留您已在 o
中应用的任何冲突解决方案),但您希望它具有 n
和 E
作为父母,而不是 o
和 E
。这实际上相当简单。
$ b
#!/ bin / sh
#1.确定$ 1
#中最近的合并。确认它来自$ 2
#3。将合并更新为$ 2的当前状态
#4.保留已经完成
#5的任何冲突解决方案,然后选择所有内容。
#最近的$ 1
update =`git rev-list -1 --min-parents = 2 $ 1`
#验证最近的合并是从正确的合并基础
test`git merge-base $ 1 $ 2`=`git rev-parse $ update ^ 2`\
|| {echo最近的合并不是从$ 2中的$ 1;出口1; }
set -e#立即出错
git checkout $ update
git merge $ 2
git checkout $(
#这会产生一个新的提交用HEAD的提交信息和树
#但是用$ update ^和$ 2作为父母
git cat-file -p HEAD \
| sed 1,/ ^ $ / d \
| git commit-tree -p $ update ^ -p $ 2 HEAD ^ {tree}
)
test $ update =`git rev-parse $ 1` || git cherry-pick $ update .. $ 1
git checkout -B $ 1
set -e
)
set -e
git checkout $ update ^
git merge $ 2
test $ update =`git rev-parse $ 1` || git cherry-pick $ update .. $ 1
git checkout -B $ 1
git合并$ 2 \
|| {echo解决冲突和\exit\`,或\`exit 1 \`不能继续; $ SHELL; }
Master A\--B--C\--D\---------E
Branch l--m---n---o--p--q
Master A\--B--C\--D\--------E\
Branch l--m---n\--o--p--q \
Tmp -------------o'-p-q
E
's history (see below), to n...D
-conflicted hunks resolved in o
. rerere
does an n...E
merge and applies any n...D
resolutions that are still valid, while this script does an standard o...E
merge (but replaces parent o
with o
) before desired after
Master A\--B--C\--D\....E \ Master A\--B--C\-D...E\
Branch l--m---n---o--p--q / Branch l--m---n------o'--p'--q'
E
-reverted n...D
conflicts, while the script will treat the reversion as a further change. Both scripts produce the "desired after" graph above, but they get there by different routes.
git checkout o
git merge E
Master A\--B--C\--D\---------E
Branch l--m---n---o\-p--q \
HEAD `--------o'
o
for o'
's parent. You do want the o'
content (to preserve any conflict resolutions you'd already applied in o
), but you want it to have n
and E
as parents, not o
and E
. That's actually fairly easy.#!/bin/sh
# 1. identify the most recent merge on $1
# 2. verify that it's from $2
# 3. update the merge to $2's current state,
# 4. preserving any conflict resolutions that were already done
# 5. and cherry-pick everything since.
# most recent merge in $1
update=`git rev-list -1 --min-parents=2 $1`
# verify most recent merge is from correct merge base
test "`git merge-base $1 $2`" = "`git rev-parse $update^2`" \
|| { echo "most recent merge isn't of $1 from $2"; exit 1; }
set -e # exit immediately on error
git checkout $update
git merge $2
git checkout $(
# this makes a new commit with HEAD's commit message and tree
# but with $update^ and $2 as parents
git cat-file -p HEAD \
| sed 1,/^$/d \
| git commit-tree -p $update^ -p $2 HEAD^{tree}
)
test $update = `git rev-parse $1` || git cherry-pick $update..$1
git checkout -B $1
o
you can instead do (from the set -e
)set -e
git checkout $update^
git merge $2
test $update = `git rev-parse $1` || git cherry-pick $update..$1
git checkout -B $1
git merge $2 \
|| { echo "Resolve conflicts and \`exit\`, or \`exit 1\` to not continue"; $SHELL; }