This post is one of a series on Git. Previously I posted on branching. When you create a branch, you diverge two lines of development. You need a way to join them back up later on, and that's what this post covers.
Before starting this, make sure you've read my other Git posts leading up to it or are comfortable working with branches in Git. This post also assumes you've been following along with the commands in the other posts. If not, you should create a repository with master and put a file named "foo" with a couple lines of text in branch master. I highly recommend that you follow along with the commands so you can see Git working.
Articles in this series:
- Part I--Distributed vs. Central VCS
- Part II--Git Started
- Part III--The Basics
- Part IV--Branching
- Part V--Merging
- Part VI--Rewriting History
- Part VII--Other Useful Stuff
- Part VIII--Connecting Git to Subversion
- Part IX--Communicating from Git to Subversion
- Part X--Communicating Between Repositories
- Follow Up--Git Quick Reference Card
Now let's get right to it.
Create a branch from master and move onto it with:
git checkout -b mergeme
Create a file named "baz" with some text in it, and commit it on this new branch:
echo "File on branch mergeme" >> baz git add baz git commit -m "Added baz on branch mergeme"
Suppose that's all the work there is to do on mergeme, and we want to merge the final result into our master branch. Just switch to master and merge the branch into it:
git checkout master git merge mergeme
You'll see output from the merge like:
Updating 645663b..bb64c2c Fast forward baz | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 baz
The first line indicates the two commits participating in the merge with the starting location first and the merge target second. The next line says "Fast forward" because Git didn't actually have to merge anything in order to make this happen. Since no commits happened on master between the time you created mergeme and the time you merged it back in, Git was able to simply "fast forward" master, meaning it just took the changes in the branch and replayed them on master. Had you made another commit on master before merging mergeme back, Git would have actually had to merge the commits together to create a new commit, which brings us to our next topic: any time an actual merge is performed, you have a chance of entering the lovely land of merge conflicts.
Merge conflicts aren't much different in Git than in any other version control. Let's create one by appending a different line to foo in each of the branches and attempting to merge them:
git checkout mergeme echo "Conflicting line in mergeme" >> foo git commit -am "Conflict in mergeme" git checkout master echo "Conflicting line in master" >> foo git commit -am "Conflict in master" git merge mergeme
If it broke as expected, the merge will have produced output like:
Auto-merging foo CONFLICT (content): Merge conflict in foo Automatic merge failed; fix conflicts and then commit the result.
When a merge is successful, the result is automatically committed. However, when there's a conflict, the results of the merge stay in your index and/or working tree. Run "git status" and examine the output. It notifies you of files needing to be merged manually, both at the top of the status output and by marking them as "unmerged". You simply need to resolve the conflicts either manually or with your tool of choice, and make sure the file gets added, then commit the final result yourself. If you've set up your own merge tool--see post two in this series--you can fix the conflict with:
Otherwise, just adjust the content of foo to remove the conflict markers, and add it:
git add foo
Either way, all changes should be staged, and you can now:
git commit -m "I merged this myself"
This merge resulted in a new commit in master because it's a real merge that entailed modifications, whereas the fast-forward we did before essentially just copied the commit from one branch to another.
That covers the basics of merging. I have a feeling I missed something, so this post may change, but for now, let's move on to the next post, where I'll show you how to rewrite history with Git. It's pretty cool: Part VI--Rewriting History
Vote for this article on DZone.