Reputation: 171
I have two branches. 'master' and 'testing'.
___testing____
/
------master--------
I want to continue with the testing branch to add features, but before that, I need to merge the testing branch to master. I want to create a third branch called 'testing2' that is exactly the same as 'testing', but comes from the 'master' branch instead of being a branch off of 'testing'.
_____testing___
/
---------master----------
\____testing2____
As an alternative, I know I can merge the 'testing' branch to 'master' and create two new branches and do my work that way,
_____testing_____ ____newtest___
/ \ /
---master-------------------------------------------------
\____continuetest_____
but is there not a way to simply duplicate the branch 'testing'?
Upvotes: 4
Views: 18714
Reputation: 489035
If you have used other version control systems—especially Mercurial, which really is a lot like Git but with some key differences including this very one here—you might expect commits to remember which branch they were made on.
In Mercurial, they do.
In Git, they don't.
In Git, think of a branch name as a sort of yellow sticky note. The note has the name of the branch on it, but it's just loosely attached to the commit itself:
<--o <--branch
The commit has its own outgoing arrow, which points to the commit's parent commit. This builds up a backwards chain of commits. If we give each commit a single letter name and draw arrows saying who points to whom, we get:
A <- B <- C <-- branch
Here A
is the very first commit ever. It has no parent—it can't have one, so it just doesn't. B
is the second commit, and its parent is A
, so B
points to A
. (Literally, B
has A
's hash ID inside it, as part of B
itself.) Likewise, C
points to B
. The name branch
remembers the big ugly hash ID of commit C
, so that we don't have to.
To make a new commit:
git add
is new, everything else is the same as before.Here is the secret of branches: Whatever branch you are on right now, Git puts the new ID into the branch name. So now branch
remembers the new commit D
we just made:
A <- B <- C <- D <-- branch
In effect, Git peels the sticky-note off the old commit and pastes it on the new one.
If you attach multiple names to one commit, and then make a new commit, Git only peels off one sticky-note. So if you make a new name that points to C
, and then make new commit D
, only the current branch name moves to D
, the old one stays with C
:
A--B--C <-- newname
\
D <-- branch
The answer is HEAD
. This is why, if you use git log --decorate
, you will see things like:
commit e0688e9... (HEAD -> master, origin/master, origin/HEAD)
This tells me that Git believes the current branch is master
, and that there are three names for the current commit e0688e9...
: master
, origin/master
, and origin/HEAD
.
Upvotes: 6
Reputation: 82994
Branching from testing
to create a testing2
branch is equivalent to creating a branch from master
that is the same as testing
.
For example:
___testing2__
___testing___/
/
------master--------
is logically equivalent to:
___testing___
/
------master--------
\___testing2__
with the same changes in the testing
and testing2
branches. It may not show like that in the log/graph, but it is the same.
Think about it more like:
X
/
------master--------
where the commit at X
has both branch labels of testing
and testing2
.
I've just created this structure to give a better view. When creating the testing2
branch, you will get:
Once you've made some commits on each branch, you will get:
Upvotes: 2
Reputation: 607
Merge with master then:
git checkout master
git branch testing2
git pull origin master
Upvotes: 1