我有以下存储库布局:

主分支(生产)集成工作

我想实现的是从工作分支中挑选一系列提交,并将其合并到集成分支中。我对git很陌生,我无法弄清楚如何在不破坏存储库的情况下准确地做到这一点(在一次操作中挑选提交范围,而不是合并)。对此有什么建议或想法吗?谢谢


当前回答

假设您有2个分支,

“branchA”:包括要复制的提交(从“commitA”到“commitB”

“branchB”:要从“branchA”转移提交的分支

1)

 git checkout <branchA>

2) 获取“commitA”和“commitB”的ID

3)

git checkout <branchB>

4)

git cherry-pick <commitA>^..<commitB>

5) 如果您有冲突,请解决并键入

git cherry-pick --continue

继续樱桃采摘过程。

其他回答

合并有时会很困难,只需创建一个补丁并手动应用更改即可。

创建从start_commit到end_commit的修补程序文件。git diff<start_commit><end_commit>>patch.diff签出分支并手动应用修补程序中的更改。

如果你只有两次提交,并且想挑选,你可以

git cherry-pick <commit> -n

然后将它们转换为新的提交。

-n不会自动创建提交,而只是阶段性地进行更改,因此您可以继续对提交中的文件进行cherry pick或更改。

从git v1.7.2起,cherry-pick可以接受一系列提交:

git cherry-pick学会了选择一系列提交(例如cherry-pick a..B和cherry--pick-stdin),git revert也学会了选择;然而,这些并不支持rebase[-i]所具有的更好的测序控制。

正如Gabe Moothart所指出的,cherry pick A..B不会得到commit A(你需要A~1..B),如果有任何冲突,git不会像rebase那样自动继续(至少在1.7.3.1)。

另一种选择可能是将我们的策略合并到范围之前的提交,然后与该范围的最后一次提交(或当它是最后一次时的分支)进行“正常”合并。因此,假设只有2345和3456个主提交要合并到功能分支中:

master:
1234
2345
3456
4567

在功能分支中:

git merge -s ours 4567
git merge 2345

以上所有选项都将提示您解决合并冲突。如果您正在合并为团队提交的更改,那么很难从开发人员那里解决合并冲突并继续。然而,“gitmerge”将一次性完成合并,但不能将一系列修改作为参数传递。我们必须使用“gitdiff”和“gitapply”命令来执行revs的合并范围。我观察到,如果补丁文件对太多文件有差异,“git-apply”将失败,因此我们必须为每个文件创建一个补丁,然后应用。请注意,脚本将无法删除在源分支中删除的文件。这是一种罕见的情况,您可以从目标分支手动删除此类文件。如果无法应用修补程序,“git-apply”的退出状态不为零,但是如果使用-3way选项,它将返回到3路合并,您不必担心此失败。

以下是脚本。

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"