Search code examples
gitgit-checkoutgit-reset

Does git checkout -B perform a reset?


I have branch called shared that is shared amongst other developers. I work off of a feature branch. Whilst on my feature branch, I ran git checkout -B shared, and got the following message:

Switched to and reset branch 'shared'
Your branch and 'origin/shared' have diverged,
and have 6 and 126 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

I pulled and resolved the conflicts and suddenly realized that my shared branch had all of my changes from my feature branch. My questions are:

  1. How did this happen exactly?

  2. Looking at the docs it says that the branch is reset when running checkout with the -B flag:

    If -B is given, <new_branch> is created if it doesn’t exist; otherwise, it is reset.

    Last time I checked, running reset on a shared branch was dangerous. Or does 'reset' have a different meaning, in this context?


Solution

  • Short Answer

    Sometimes. git checkout -B <branch_name> performs a reset if branch_name already exists.

    Details

    Why did this happen, exactly?

    As you indicated, git checkout -B <shared> resets shared to the HEAD commit and checks out shared. What does this do, exactly?

    • Point shared at your current HEAD commit. (This answers your first question).
    • Empty everything you recently added out of your index.
    • Checkout shared.

    In other words, you reset shared to match feature. Here's an example that shows how you were before the checkout -B:

     > git log --oneline --decorate --all --graph
    
     * d0d0d0d (HEAD, feature) Some commit message.
     * e0e0e0e Some commit message.
     * f0f0f0f Some commit message.
     * g0g0g0g Some commit message. 
     * h0h0h0h Some commit message. 
     * i0i0i0i Some commit message. 
     |     * z0z0z0z (origin/shared) Some commit message.
     |     * y0y0y0y (origin/shared) Some commit message.
     |     * x0x0x0x (origin/shared) Some commit message.
     |     ---- 120 more commits ----
     |     * w0w0w0w (origin/shared) Some commit message.
     |     * v0v0v0v (origin/shared) Some commit message.
     |     * u0u0u0u (origin/shared) Some commit message.
     |   /   
     | /     
     * a0a0a0a (shared) Some commit message.
     * b0b0b0b Some commit message.
     * c0c0c0c Some commit message.
    

    And here's how you were after the checkout -B:

     > git checkout -B shared
     > git log --oneline --decorate --all --graph
    
     * d0d0d0d (HEAD, feature, shared) Some commit message.
     * e0e0e0e Some commit message.
     * f0f0f0f Some commit message.
     * g0g0g0g Some commit message. 
     * h0h0h0h Some commit message. 
     * i0i0i0i Some commit message. 
     |     * z0z0z0z (origin/shared) Some commit message.
     |     * y0y0y0y (origin/shared) Some commit message.
     |     * x0x0x0x (origin/shared) Some commit message.
     |     ---- 120 more commits ----
     |     * w0w0w0w (origin/shared) Some commit message.
     |     * v0v0v0v (origin/shared) Some commit message.
     |     * u0u0u0u (origin/shared) Some commit message.
     |   /   
     | /     
     * a0a0a0a Some commit message.
     * b0b0b0b Some commit message.
     * c0c0c0c Some commit message.
    

    shared will now have all the changes from feature, your shared will have 6 different commits thatorigin/shared`, and likewise it will have 126 different commits than yours.

    Does 'reset' have a different meaning, in this context?

    Reset has the same meaning as it always does. You basically did the following:

    git checkout shared
    git reset --mixed feature
    

    A Good Fix

    All I wanted to do was pull down shared and merge in feature. Is there a way to undo this?

    @kdopen's comment suggests a good fix. Though both the fetch and the --hard option on reset are optional (see comments on the question for details). Here's my modified fix.

    git checkout shared 
    git reset origin/shared
    

    That should land you in this position, from which you can merge in your feature branch as intended.

     * d0d0d0d (feature) Some commit message.
     * e0e0e0e Some commit message.
     * f0f0f0f Some commit message.
     * g0g0g0g Some commit message. 
     * h0h0h0h Some commit message. 
     * i0i0i0i Some commit message. 
     |     * z0z0z0z (HEAD, shared, origin/shared) Some commit message.
     |     * y0y0y0y (origin/shared) Some commit message.
     |     * x0x0x0x (origin/shared) Some commit message.
     |     ---- 120 more commits ----
     |     * w0w0w0w (origin/shared) Some commit message.
     |     * v0v0v0v (origin/shared) Some commit message.
     |     * u0u0u0u (origin/shared) Some commit message.
     |   /   
     | /     
     * a0a0a0a Some commit message.
     * b0b0b0b Some commit message.
     * c0c0c0c Some commit message.