Let’s go through a simple example of branching and merging with a workflow that you might use in the real world.You’ll follow these steps:
At this stage, you’ll receive a call that another issue is critical and you need a hotfix.You’ll do the following:
Basic BranchingFirst, let’s say you’re working on your project and have a couple of commits already on the ![]() Figure 18. A simple commit history You’ve decided that you’re going to work on issue #53 in whatever issue-tracking system your company uses.To create a new branch and switch to it at the same time, you can run the $ git checkout -b iss53Switched to a new branch 'iss53' This is shorthand for:
![]() Figure 19. Creating a new branch pointer You work on your website and do some commits.Doing so moves the $ vim index.html$ git commit -a -m 'added a new footer [issue 53]' ![]() Figure 20. The iss53 branch has moved forward with your workNow you get the call that there is an issue with the website, and you need to fix it immediately.With Git, you don’t have to deploy your fix along with the However, before you do that, note that if your working directory or staging area has uncommitted changes that conflict with the branch you’re checking out, Git won’t let you switch branches.It’s best to have a clean working state when you switch branches.There are ways to get around this (namely, stashing and commit amending) that we’ll cover later on, in Stashing and Cleaning.For now, let’s assume you’ve committed all your changes, so you can switch back to your
At this point, your project working directory is exactly the way it was before you started working on issue #53, and you can concentrate on your hotfix.This is an important point to remember: when you switch branches, Git resets your working directory to look like it did the last time you committed on that branch.It adds, removes, and modifies files automatically to make sure your working copy is what the branch looked like on your last commit to it. Next, you have a hotfix to make.Let’s create a $ git checkout -b hotfixSwitched to a new branch 'hotfix'$ vim index.html$ git commit -a -m 'fixed the broken email address'[hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+) ![]() Figure 21. Hotfix branch based on master You can run your tests, make sure the hotfix is what you want, and finally merge the
You’ll notice the phrase “fast-forward” in that merge.Because the commit Your change is now in the snapshot of the commit pointed to by the ![]() Figure 22. master is fast-forwarded to hotfix After your super-important fix is deployed, you’re ready to switch back to the work you were doing before you were interrupted.However, first you’ll delete the $ git branch -d hotfixDeleted branch hotfix (3a0874c). Now you can switch back to your work-in-progress branch on issue #53 and continue working on it.
![]() Figure 23. Work continues on iss53 It’s worth noting here that the work you did in your Basic MergingSuppose you’ve decided that your issue #53 work is complete and ready to be merged into your $ git checkout masterSwitched to branch 'master'$ git merge iss53Merge made by the 'recursive' strategy.index.html | 1 +1 file changed, 1 insertion(+) This looks a bit different than the ![]() Figure 24. Three snapshots used in a typical merge Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it.This is referred to as a merge commit, and is special in that it has more than one parent. ![]() Figure 25. A merge commit Now that your work is merged in, you have no further need for the
Basic Merge ConflictsOccasionally, this process doesn’t go smoothly.If you changed the same part of the same file differently in the two branches you’re merging, Git won’t be able to merge them cleanly.If your fix for issue #53 modified the same part of a file as the $ git merge iss53Auto-merging index.htmlCONFLICT (content): Merge conflict in index.htmlAutomatic merge failed; fix conflicts and then commit the result. Git hasn’t automatically created a new merge commit.It has paused the process while you resolve the conflict.If you want to see which files are unmerged at any point after a merge conflict, you can run
Anything that has merge conflicts and hasn’t been resolved is listed as unmerged.Git adds standard conflict-resolution markers to the files that have conflicts, so you can open them manually and resolve those conflicts.Your file contains a section that looks something like this: <<<<<<< HEAD:index.html<div id='footer'>contact : email.support@github.com</div>=======<div id='footer'> please contact us at support@github.com</div>>>>>>>> iss53:index.html This means the version in
This resolution has a little of each section, and the If you want to use a graphical tool to resolve these issues, you can run $ git mergetoolThis message is displayed because 'merge.tool' is not configured.See 'git mergetool --tool-help' or 'git help config' for more details.'git mergetool' will now attempt to use one of the following tools:opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emergeMerging:index.htmlNormal merge conflict for 'index.html': {local}: modified file {remote}: modified fileHit return to start merge resolution tool (opendiff): If you want to use a merge tool other than the default (Git chose
After you exit the merge tool, Git asks you if the merge was successful.If you tell the script that it was, it stages the file to mark it as resolved for you.You can run
If you’re happy with that, and you verify that everything that had conflicts has been staged, you can type Merge branch 'iss53'Conflicts: index.html## It looks like you may be committing a merge.# If this is not correct, please remove the file# .git/MERGE_HEAD# and try again.# Please enter the commit message for your changes. Lines starting# with '#' will be ignored, and an empty message aborts the commit.# On branch master# All conflicts fixed but you are still merging.## Changes to be committed:# modified: index.html# If you think it would be helpful to others looking at this merge in the future, you can modify this commit message with details about how you resolved the merge and explain why you did the changes you made if these are not obvious. |
|