Part 3
Organizing Your Repository with Branches and Tags

Now that you have the basics down, it’s time to learn about branches. Branches allow you to segregate different lines of development. They’re integral how Git works, so having a good conceptual understanding of what they are is crucial to becoming proficient with Git.

Version control systems of yesterday had poor support for branches and even worse support for merging those branches back together. Git changes this. In fact, one of the most compelling features of Git is its ability to easily handle creating branches and gracefully merge them back together.

Branches track changes to multiple versions of a project. For example, you might be finishing up version 1.0 and already starting on new features for version 1.1. Using branches, you can keep the code from version 1.0 isolated so new features from 1.1 don’t accidentally slip into the version that is getting ready to release.

You give branches names, making it easier track them based on their name, rather than some commit ID. master is the name of the default branch that Git uses. All your commits so far in this book have been in that branch. You can create as many branches as you want.

Branches in Git are relatively simplistic—they’re simply a text file inside the repository that marks the latest commit in the branch. Treating branches as pointers makes operations with branches painless and fast.

There are several different ways to approach using branches. One approach is the topic branch. You can use this style of branch to work on a specific feature, fix a bug, or deal with any other “topic.” Once it’s complete, then you merge the finished changes back into your master branch.

Another common type of branch is the release branch, the type of branch mentioned earlier. You create release branches as you approach a release in your project. They’re useful when you or other members on your team are working on multiple versions of your project.

You can create a branch called release_v1.0 for the 1.0 version to isolate that release from features that aren’t supposed to ship until version 1.1. Work on version 1.1 continues like normal in the master branch, and any changes from the final work on version 1.0 get merged back into master.

You can use tags to mark milestones in your project, such as releases. Tags are similar to branches, except they are read-only. Once you create a tag, you can’t change it. Well, that’s almost true, but for now consider them completely unchangeable.

Branches and tags are not shared by default. Like commits, you’re given the ability to decide which branches and tags to share with other developers and when.

Branches in Git are pointers to a specific commit in your repository’s history. Since each commit knows about its parent (or parents), Git can reconstruct what’s in a branch by looking at the latest commit in that branch and walking the history backward to find all the ancestors. This simplified approach to branches makes them quick to create, rename, merge, and even delete.

You occasionally have to merge changes between branches to keep from duplicating the same work in different branches. Git makes this easy by tracking which commits have been merged between branches for you. Many modern VCS do not do this at all or do it poorly.

images/fast-forward-merge.png

Figure 3. Before and after a fast-forward merge

Git can employ several different merge strategies to merge branches together. The first is the fast-forward merge. Fast-forwards are performed when two conditions are met: when the branch you are merging in is being merged back into the branch it was created from and when the original branch hasn’t had any new commits since the branch was created. For an example, check out Figure 3, Before and after a fast-forward merge.

Fast-forward merges do not actually create anything new in the repository. They “fast-forward” the branch pointer to the new location.

Recursive merges are used by default when both the branches have commits that are not in the other branch. Git creates a merge commit that has two parent commits—the latest commit in each branch (see Figure 4, Before and after a recursive merge).

images/recursive-merge.png

Figure 4. Before and after a recursive merge

Another way to get information from one branch into another is through rebasing the branch. Rebasing is a powerful tool in Git that’s often misunderstood, which is understandable—there’s no corollary in traditional VCS. It’s best explained with an example workflow.

Consider the following example.

Rebasing Changes

You start your morning by pulling in all the changes from the company’s shared repository and then start working. During the morning, your co-worker pushes some commits upstream. When you try to push the commits you’ve made, you get an error. You now have two options. You can fetch the changes and do the following:

  1. Merge them into your local branch, creating a merge commit.

  2. Rebase your local branch on top of the remote branch.

Rebasing takes the commits you made this morning and then replays them, one by one, starting on the other branch. You can do this to keep the appearance of a continuous stream of development instead of having a bunch of merge commits scattered throughout your repository’s history.

Now, let’s see what’s covered in this part:

  • Before you can use branches, you must create them. You will learn how to do that in Task 13, Creating and Switching Branches.

  • Keeping track of your branches requires that you be able to see what branches you have. Task 14, Viewing Branches covers the commands you need to know in order to see the branches you have in your repository.

  • Having multiple branches to separate work on your project into different areas is useful only if you can merge the changes all back together. You learn this in Task 15, Merging Commits Between Branches.

  • No coverage of merging is complete without talking about rebasing. Rebasing is often misunderstood and feared, so Task 16, Rewriting History by Rebasing gets you comfortable with the mechanics of rebasing.

  • Branches often outlive their intended use. Once you no longer need a branch, you can then delete it using the methods described in Task 17, Deleting Branches.

  • Finally, you need to be able to mark milestones in your branches. We cover that in Task 18, Tagging Milestones.

At first glance, it might seem odd that branches—generally considered an advanced topic in most version control systems—are covered before discussing how to collaborate with a team. There is a reason for this. Remotes in Git are read-only branches. Once you know how to work with a branch, you know how to interact with a remote repository minus a couple of extra commands we’ll cover when we get there.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.255.87