Search code examples
gitgitlabgit-cherry-pick

Cherry picking a commit that was overwritten by a push force


These are the commits on a branch on origin:

A -> B -> C1

Locally, I had the branch when it only had A -> B commits and I add a new commit. So the branch locally looks like:

A -> B -> C2

I do a push force and overwrite the remote branch so it removes C1 commit and replaces it with C2.

Is it possible to get C1 back and add it back to the branch?

I tried with cherry pick, but I get fatal: bad revision. However, I was able to cherry pick it using gitlab's web interface. Is this possible without gitlab?


Solution

  • You need to find a repository that actually has the commit in it.

    Clearly, your repository didn't:

    I tried with cherry pick, but I get fatal: bad revision

    Clearly their repository (the one you force-pushed to) had it before. Whether they still do depends on (a) whether the commit was reachable by some other means, and if not, (b) how aggressive they are about garbage-collecting unreachable commits.

    If there are other users of the upstream repository, those other users may have copied the commit into their repositories.

    Note that when you do obtain C1 again and use cherry-pick on it, you get a new and different commit that has the same effect as C1, and the same author as C1, but you as the committer. You could call this C3, or—to indicate how similar it is to the original C1—you could call it C1'. As eftshift0 noted in a comment, the end result is:

    A <-B <-C2 <-C1'   <-- branch
    

    If other people still have commit C1, they may attempt to re-introduce it. This will usually be harmless: depending on how they make this attempt, it might either just remove their copy, or it might make a merge that has no effect:

         C2--C1'
        /      \
    A--B        M   <-- branch
        \      /
         --C1--
    

    This sort of thing is why it's generally unwise to rebase and/or force-push-away other people's commits. If they're not expecting it, they'll re-introduce their commits, even though you've made new commits that subsume their work.

    If all users of all of the various clones of these repositories agree that rebasing / cherry-picking and force-pushing do get used on this branch name, then in that case it's fine. It's up to each user to notice that this has happened (if necessary) and do whatever is required (if anything) to compensate for it.