Reputation: 2443
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:
How did this happen exactly?
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?
Upvotes: 2
Views: 582
Reputation: 141742
Sometimes. git checkout -B <branch_name>
performs a reset if branch_name
already exists.
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?
shared
at your current HEAD commit. (This answers your first question).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 that
origin/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
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.
Upvotes: 1
Reputation: 18129
git checkout -b
and git checkout -B
are used to checkout a (new) branch from a commit. -B
is used to possibly re-use an existing branch by resetting it or otherwise creating it and -b
is used to create a new one without the possibility of re-using an existing one.
git checkout -B shared
is the same thing as
git checkout -B shared HEAD
and it means
If a branch named shared
exists, check it out and reset it to HEAD
(in your case, HEAD
was the tip of feature
). If no branch named shared
exists, create one based on HEAD
.
What happened: You reset shared
to feature
and then pulled in origin/shared
(and solved the conflicts)
Upvotes: 1
Reputation: 490078
The default starting position for a new branch (git checkout -b newbr
) is HEAD
.
This is also true for the reset action of "create-or-reset" git checkout -B oldbr
. So since you were on feature
, HEAD
said feature
which resolved to the ID of the tip-most commit on branch feature
, which made your existing branch label shared
point to that same commit.
Fortunately shared@{1}
will have its previous position, so you can simply git reset shared@{1}
(if you use csh or tcsh, you must quote the open brace, e.g., shared@\{1}
or 'shared@{1}'
; not sure about some other shells).
Upvotes: 1