Search code examples
gitgit-cherry-pick

Cherry-picking from a commit that is inconsistent with the current state of the repository


Cherry-picking is applying a sequence of diffs, copied from an arbitrary commit, to the current state of the repository. What happens if some of these diffs are inconsistent with the current state of the repository? For instance, what if one of the diffs modifies a file f, but this file no longer exists in the current repository?


Solution

  • In a situation like this, a conflict occurs. Git pauses the cherry-pick and waits for you to resolve the conflict or abort the cherry-pick. Conceptually, this is the same as a conflict that might arise due to a git merge or a git rebase.

    what if one of the diffs modifies a file f, but this file no longer exists in the current repository

    Git would present you with the choice between keeping the file you're cherry-picking, keeping the file deleted or manually updating the file.

    It's very easy to see for yourself how this works.

    1. Somewhere in your file system (outside of existing Git repositories), create a new directory and enter it.

      mkdir cherry
      cd cherry
      
    2. Initialize an empty Git repository

      git init
      
    3. Create a file and add some content to it

      echo "Some changes" > README.md
      
    4. Add the file to the index and commit the changes

      git add README.md
      git commit -m "Added some content to the readme"
      
    5. Create and check out a new branch

      git checkout -b feature/readme-update
      
    6. Change the README.md file again

      echo "New content of README" > README.md
      
    7. Stage and commit the changes

      git add README.md
      git commit -m "Added more to readme"
      

      Save the hash of the last commit.

    8. Go back to master and delete the file, commit the change

      git checkout master
      git rm README.md
      git commit -m "Removed the readme"
      
    9. Cherry-pick the commit from feature/readme-update where you changed the contents of the README.md file

      git cherry-pick <commit-hash>
      
    10. You have a conflict on your hands

      tomek@LAPTOP-SGL6966J MINGW64 /c/repos/cherry (master)
      $ git cherry-pick <commit-hash>
      error: could not apply 4a99ca7... Added more to readme
      hint: after resolving the conflicts, mark the corrected paths
      hint: with 'git add <paths>' or 'git rm <paths>'
      hint: and commit the result with 'git commit'
      
      tomek@LAPTOP-SGL6966J MINGW64 /c/repos/cherry (master|CHERRY-PICKING)
      

      git status will also tell you the same thing

      $ git status
      On branch master
      You are currently cherry-picking commit 4a99ca7.
        (fix conflicts and run "git cherry-pick --continue")
        (use "git cherry-pick --abort" to cancel the cherry-pick operation)
      
      Unmerged paths:
        (use "git add/rm <file>..." as appropriate to mark resolution)
      
          deleted by us:   README.md
      

      In this case, you can remove the file (accept the changes from master) or add it (accept the changes you're cherry-picking). Another option is to manually adjust the file in whatever manner you deem sensible.

      Regardless of what changes you accept, apply them to the file, stage them and continue with the cherry-pick by calling git cherry-pick --continue

      If you're confused and no longer want to proceed with the cherry-pick, abort it by calling git cherry-pick --abort