rebase --onto 会更好,您可以在集成分支上重放给定的提交范围,如Charles Bailey described here . (另外,在git rebase man page中查找"Here is how you would transplant a topic branch based on one branch to another",查看 git rebase --onto 的实际示例)
如果您当前的分支是集成:
# Checkout a new temporary branch at the current location
git checkout -b tmp
# Move the integration branch to the head of the new patchset
git branch -f integration last_SHA-1_of_working_branch_range
# Rebase the patchset onto tmp, the old location of integration
git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration
这将重播之间的一切:
first_SHA-1_of_working_branch_range 的父级之后的
(因此 ~1 ):您要重播的第一次提交
最多为“ integration ”(指向您要重播的最后一次提交,来自 working 分支)
到“ tmp ”(指向 integration 之前指向的位置)
如果在重播其中一个提交时发生任何冲突:
要么解决它并运行“ git rebase --continue ” .
或跳过此补丁,改为运行“ git rebase --skip ”
或用“ git rebase --abort ”取消所有内容(并在 tmp 分支上放回 integration 分支)
在那之后 rebase --onto , integration 将返回到集成分支的最后一次提交(即“ tmp ”分支所有重放的提交)
通过采摘樱桃或 rebase --onto ,不要忘记它会对后续合并产生影响,如described here .
#!/bin/bash
if [ -z $1 ]; then
echo "Equivalent to running git-cherry-pick on each of the commits in the range specified.";
echo "";
echo "Usage: $0 start^..end";
echo "";
exit 1;
fi
git rev-list --reverse --topo-order $1 | while read rev
do
git cherry-pick $rev || break
done
enter code here
#!/bin/bash
# This script will merge the diff between two git revisions to checked out branch
# Make sure to cd to git source area and checkout the target branch
# Make sure that checked out branch is clean run "git reset --hard HEAD"
START=$1
END=$2
echo Start version: $START
echo End version: $END
mkdir -p ~/temp
echo > /tmp/status
#get files
git --no-pager diff --name-only ${START}..${END} > ~/temp/files
echo > ~/temp/error.log
# merge every file
for file in `cat ~/temp/files`
do
git --no-pager diff --binary ${START}..${END} $file > ~/temp/git-diff
if [ $? -ne 0 ]
then
# Diff usually fail if the file got deleted
echo Skipping the merge: git diff command failed for $file >> ~/temp/error.log
echo Skipping the merge: git diff command failed for $file
echo "STATUS: FAILED $file" >> /tmp/status
echo "STATUS: FAILED $file"
# skip the merge for this file and continue the merge for others
rm -f ~/temp/git-diff
continue
fi
git apply --ignore-space-change --ignore-whitespace --3way --allow-binary-replacement ~/temp/git-diff
if [ $? -ne 0 ]
then
# apply failed, but it will fall back to 3-way merge, you can ignore this failure
echo "git apply command filed for $file"
fi
echo
STATUS=`git status -s $file`
if [ ! "$STATUS" ]
then
# status is null if the merged diffs are already present in the target file
echo "STATUS:NOT_MERGED $file"
echo "STATUS: NOT_MERGED $file$" >> /tmp/status
else
# 3 way merge is successful
echo STATUS: $STATUS
echo "STATUS: $STATUS" >> /tmp/status
fi
done
echo GIT merge failed for below listed files
cat ~/temp/error.log
echo "Git merge status per file is available in /tmp/status"
7 回答
当涉及到一系列提交时,采摘樱桃是不切实际的 .
作为mentioned below Keith Kim,Git 1.7.2引入了挑选一系列提交的能力(但你还需要知道consequence of cherry-picking for future merge)
damian comments并警告我们:
如果你想选择 range B through D (inclusive) ,那将是 B^..D .
请参阅“Git create branch from range of previous commits?”作为说明 .
如Jubobs提到in the comments:
注意:从Git 2.9.x / 2.10(2016年第3季度)开始,您可以直接在孤立分支(空头)上挑选一系列提交:请参阅“How to make existing branch an orphan in git” .
原始答案(2010年1月)
rebase --onto
会更好,您可以在集成分支上重放给定的提交范围,如Charles Bailey described here .(另外,在git rebase man page中查找"Here is how you would transplant a topic branch based on one branch to another",查看
git rebase --onto
的实际示例)如果您当前的分支是集成:
这将重播之间的一切:
first_SHA-1_of_working_branch_range
的父级之后的(因此
~1
):您要重播的第一次提交最多为“
integration
”(指向您要重播的最后一次提交,来自working
分支)到“
tmp
”(指向integration
之前指向的位置)如果在重播其中一个提交时发生任何冲突:
要么解决它并运行“
git rebase --continue
” .或跳过此补丁,改为运行“
git rebase --skip
”或用“
git rebase --abort
”取消所有内容(并在tmp
分支上放回integration
分支)在那之后
rebase --onto
,integration
将返回到集成分支的最后一次提交(即“tmp
”分支所有重放的提交)通过采摘樱桃或
rebase --onto
,不要忘记它会对后续合并产生影响,如described here .一个纯粹的“
cherry-pick
”解决方案是discussed here,并且会涉及到以下内容:但无论如何,当你需要"replay"一系列提交时,单词"replay"会推动你使用Git的“
rebase
”功能 .从git v1.7.2开始,cherry pick可以接受一系列提交:
你确定你不想真正合并分支吗?如果工作分支有一些您不想要的最近提交,您可以在您想要的位置创建一个带有HEAD的新分支 .
现在,如果你真的想要挑选一系列的提交,无论出于何种原因,一个优雅的方法是只需要一个补丁集并将其应用到你的新集成分支:
这基本上就是git-rebase正在做的事情,但不需要玩游戏 . 如果需要合并,可以将
--3way
添加到git-am
. 如果您逐字按照说明操作,请确保在您执行此操作的目录中没有其他* .patch文件...假设你有2个分支,
“branchA”:包括您要复制的提交(从“commitA”到“commitB”)
“branchB”:您希望从“branchA”传输提交的分支
1)
2)获取“commitA”和“commitB”的ID
3)
4)
5)如果您有冲突,请解决并输入
继续樱桃采摘过程 .
我将VonC's code包装成一个简短的bash脚本
git-multi-cherry-pick
,以便于运行:我现在将核心第三方代码,第三方模块和自定义分离到他们自己的git分支上,以便更好地理解未来的自定义 .
git-cherry-pick
在这种情况下很有用,因为我在同一个存储库中有两棵树,但没有共享的祖先 .以上所有选项都将提示您解决合并冲突 . 如果要合并为团队所做的更改,则很难解决开发人员的合并冲突并继续 . 但是,“git merge”将一次性完成合并,但您无法通过一系列修订作为参数 . 我们必须使用“git diff”和“git apply”命令来进行转速的合并范围 . 我观察到如果补丁文件包含太多文件的差异,“git apply”将失败,因此我们必须为每个文件创建一个补丁然后应用 . 请注意,该脚本将无法删除源分支中删除的文件 . 这是一种罕见的情况,您可以从目标分支手动删除此类文件 . 如果它不能应用补丁,“git apply”的退出状态不为零,但是如果你使用-3way选项,它将回退到3路合并,你不必担心这个失败 .
下面是脚本 .
另一种选择可能是将我们的策略与范围之前的提交合并,然后与该范围的最后一次提交(或最后一次提交时的分支)进行“正常”合并 . 因此假设只有2345和3456提交的master被合并到feature分支中:
在功能分支中: