Search code examples
gitcommitcherry-pick

cherry pick multiple commits as one without going through each one git apply patch


I have branch A with a few commits I need to cherry-pick into branch B. In the first cherry-picks I've added code that I've later removed in the last commits.

When I try to cherry pick them using first_commit^..last_commit it still cherry-picks the commits one by one - forcing me to solve conflicts between the code I added in the first commits and other developers code, even though I don't really need to solve these conflicts- as I've deleted this code in the last commits I'm trying to cherry-pick anyway!

So my question is: is there a way to cherry-pick a range of commits without going through them one by one (solving conflicts for each one of them)- but only the end result of their changes in code (solving conflicts, if any, between the changes after all the commits were applied and the rest of the code).

P.S. I cannot pull A into B as it contains other content I don't want, and I think I've also tried rebasing with similar results..

Thanks!


Solution

  • One quick way can be : instead of cherry-picking a sequence of individual commits you can create one single squashed commit using git merge --squash.


    If you want to have a sequence of commits in the end result, then you will need to use cherry-pick or rebase to replay individual commits, and you may have to solve conflicts on a per commit basis.

    You can try to avoid cherry-picking the problematic commits :

    if your starting history looks like this :

    *--*--*--*--*--*--*--*--*--* <- main
        \
         \
          x1--a--b--c--d--e--x2 <- feature
          ^                  ^
      problematic commit     |
                         revert of commit x1
    

    you can try to run git cherry-pick x1..e (all commits up to e, excluding x1) instead of git cherry-pick main..feature (all commits up to feature excluding main, but including x1 and x2)


    [update] from your comment, it looks like you want to edit your history (e.g: split some existing commits into "parts you want to keep" vs "parts you want to discard"). There are several ways to do that :

    if you can afford to squash all your devs in one single commit, here is one way :

    • form your branch, create a temporary branch :
    git checkout -b wip
    
    • to squash your commits together, spot the <sha> of the commit where your branch forked from master branch, and use git reset --soft :
    git reset --soft <sha>
    git commit -m "my devs in one single commit"
    
    • now repeat several time : inspect the diff with previous commit, remove a piece of code from your commit
    git diff HEAD^ HEAD
    # edit a file
    git add file
    git commit --amend
    

    Once you have a result which contains only what you want to port, you can rebase or merge with target branch