Simple Merging
So now we want to move the changes in our newfunc
branch
back into our master
branch and remove it.
This will require us merging one branch into another.
Since we're already in our master
branch,
we'll merge in the newfunc
branch like this:
git merge newfunc
Easy peasy.
We can see that the simplegit.rb
file now has four new lines
and the README
file was auto-merged.
Now we can get rid of our 'newfunc' branch with a simple:
$ git branch -d newfunc
Deleted branch newfunc.
Resolving Conflicts
That was a fairly simple problem, but what if we branch our code and then edit the same place in a file in different ways in each branch? In that case, we'll get a conflict when we try to merge them back together. Git is not too aggressive in trying to resolve conflicts, since you don't want it to make assumptions that are not necessarily correct, so bugs aren't introduced without your knowledge.
Let's say that we created a versioning
branch
and then modified the version in the Rakefile
to different versions
in both the new branch and the master
branch,
then tried to merge them together.
$ git merge versioning
Auto-merged Rakefile
CONFLICT (content): Merge conflict in Rakefile
Automatic merge failed; fix conflicts and then commit the result.
It tells us that there was a conflict
and so the new commit object was not created.
We will have to merge the conflicted file manually
and then commit it again.
The output tells us the files that had conflicts,
in this case it was the Rakefile
.
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "simplegit"
<<<<<<< HEAD:Rakefile
s.version = "0.1.2"
=======
s.version = "0.2.0"
>>>>>>> versioning:Rakefile
s.author = "Scott Chacon"
s.email = "schacon@gmail.com"
s.summary = "A simple gem for using Git in Ruby code."
s.files = FileList['lib/**/*'].to_a
s.require_path = "lib"
end
We can see that in the master
branch,
the version was changed to 0.1.2
and in the versioning
branch,
the same line was changed to 0.2.0
.
All we have to do is choose which one is correct
and remove the rest of the lines,
like so:
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "simplegit"
s.version = "0.2.0"
s.author = "Scott Chacon"
s.email = "schacon@gmail.com"
s.summary = "A simple gem for using Git in Ruby code."
s.files = FileList['lib/**/*'].to_a
s.require_path = "lib"
end
Now we add and commit that file, and we're good.
$ git add Rakefile
$ git commit -m 'fixed conflict'
Created commit 47c668a: fixed conflict
Undoing a Merge
Assume we have gone through some massive merge
because someone on your team hasn't committed in a while,
or you have a branch that was created some time ago
but hasn't been rebasing and you want to pull it in.
So you try to git merge old_branch
it
and you get conflict after conflict
and it is just too much trouble to deal with
and you just want to undo it all.
This is where git reset
comes in.
To reset your working directory and index back to what it was
before you tried the merge,
simply run:
git reset --hard HEAD
The --hard
makes sure both your index file and working directory
are changed to match what it used it be.
By default it will only reset your index,
leaving the partially merged files in your working directory.
If you happen to have worked through it all and committed,
then decided that it was a mistake
because all of your tests break or something,
you can still go back (and throw away that commit) by running:
git reset --hard ORIG_HEAD
This is only helpful if you want to undo the latest change or changes.
If you happen to commit again
then decide that you want to keep the latest commit,
but undo a commit that was added sometime before that,
you'll need to use git revert
,
which is a bit too dangerous to cover here.