At some point, you’ll probably want to switch context within a project and work on something else. Git branches are a possible strategy. What happens when you have to fix a bug after you’ve branched, and you don’t want to step on your feature? In this article, we will discuss commands to:
- Create a branch from master to work a feature
- “Work” the feature
- Handle a bug in the middle of working the feature
- Merging the branch back into master
If you don’t have an existing repository, or a bonafide project repository to try it on, try setting one up for fun using this earlier post!
Let’s get to work!
I’m going to assume you have a git repo handy, otherwise, feel free to go create on using this earlier post! A super handy command to have in your arsenal when branching is: git branch -av
. This command should show you any branches you have in your local repo, including tracking branches (the -a
switch) which we’ll talk about in a future post:
We haven’t done any branching yet, so we’re only showing that we have a branched called master, it’s checked out, and the last commit message was “first!” (the -v
switch shows this level of verbosity.)
Now we’ve decided we want to build a new feature in a development capacity, and we know it will take a couple days. So, we create a branch, leaving the master branch in tact and able to address bug fixes, while we work in the new branch we’ll call sweetfeature:
git branch sweetfeature
git branch -av
git checkout sweetfeature
Alternatively, we could run git checkout -b sweetfeature
, and git would have automagically created the branch called sweetfeature, and checked it out:
A note about the [master] notation: I have installed posh-git. It’s a great module that enhances your prompt to describe the state of a git repository. It’s not required, but if you’d like to install it, check this out.
Working in the branch
Now that we’re working on our feature, let’s start wiring it up! We’re going to commit a quick change to the existing file for our super awesome feature.
Let’s recap the screenshot above. We:
- Made a change to our program file awesomeprogram.txt
- Checked it visually with
git diff
- Added and committed our work to the new branch
Oh no–there’s a bug in production!
So what happens when your marketing team member comes to you and says, “Hey, there’s a problem with production, and I submitted a ticket. It needs to be fixed ASAP!” since literally all marketing problems are stop-everything emergencies that need to be fixed yesterday.
Good thing we’re working our feature in a branch! All we need to do is:
- Checkout the master branch (remember, production code is still running here)
- Fix the bug
- Commit our work
Phew! Now that our marketing emergency has been handled, we can get back to our feature work. Let’s checkout the sweetfeature branch and merge master into the branch so we will be working on the latest code from production. But alas, there is a merge conflict.
After I checked out sweetfeature, I ran git merge master
to say, “Hey git, please give me all the code from master and try to merge if you can.” Fortunately, git stopped and didn’t just mash my code together. It told me there was a CONFLICT in awesomeprogram.txt, so we need to fix it by using a command like: git mergetool
.
Please note that my merge.tool configuration is set to use Visual Studio, so your mileage may vary.
Once git mergetool has been run, git will open your merge tool once for each conflicted file. As a developer, you’re responsible for resolving the merge conflict(s).
This one is a little tricky. The merge conflict occurred because one of the lines of sweetfeature changed in master, so we need to handle it.
First, we check the box on the left, since it’s clearly been updated since we started our feature work, and we definitely didn’t modify it in the course of our work.
Next, we need to manually copy the lines of code (one line in this case) from the LOCAL pane on the top-right into the Result pane at the bottom. Yes, this is tedious, but master and sweetfeature have no knowledge of one another, so the developer is responsible for resolving the conflict.
Finally, still in Visual Studio (or your merge tool,) we need to accept the merge by clicking the Accept Merge button. For the purposes of this article, Visual Studio closes, and we’re left in a merge state in git (this is a good thing):
Now that we’ve resolved the conflict, we still need to commit our merge resolution with: git commit -m "merge resolved"
.
You might notice posh-git is still telling us that we have outstanding changes by the
+1 ~0 -0 !
notation. This outstanding file, awesomeprogram.txt.orig, is a backup of the file(s) we changed during the merge, just in case we needed to reference what we changed. If you want to get rid of untracked files, you can rungit clean -df
.
Finally, we’re ready to merge our feature back into master (production) and ship it! So, let’s:
- Checkout the master branch
- Merge sweetfeature into master
- Review our work
Note the “Fast-forward” during the merge command. Since we’ve already resolved all existing merge conflicts, git is smart enough to know how to merge these branches together now. The ancestry of all files and their merge differences is completely known, so git has virtually no work to do. Lastly, we use the more
command to confirm that our sweetfeature branch did indeed get merged into master along with the emergency bug fix!
Summary
Merging and branching are important components of source control. They’re not always as trivial as this example, and often you’ll be working in teams. So, merge conflict resolution may mean running around to grab whomever worked a feature or a bug fix or some other work item. Don’t be discouraged. Use your tooling and always be on the lookout for easier ways to do things!