An introduction to Git (part 4): Git branches

By shane
Tue, 2015-02-03 19:58
4 comments

Share with Others

In the last section, An introduction to Git Part 3, you learned about adding and committing files to your Git repository. In this section, you will learn about Git branches and how using Git branches can help your Drupal development process. You will also learn a few different Git branch methodologies you can try out in your own Drupal projects.

Git is one of the secrets from my 5 secrets to becoming a Drupal 7 Ninja ebook, and much of the following posts are from this ebook. To learn more about Git and the other secrets, please consider purchasing the ebook or signing up for the 5 secrets email newsletter which will give you more information about the 5 secrets.

An Introduction to Git Branches

To me, Git branches are the most powerful feature Git has to offer. Initially they seem very complicated, but they are actually simple once you understand their uses and their benefits. One thing to keep in mind is that Git branches are incredibly flexible. Entire books and blogs have been written on how Git branches can be used in a specific way to build the ideal development process for various types of software. With that in mind, we will only be scratching the surface of
what Git branches offer.

Let’s start with a practical and possibly old fashioned example. Assume you are writing some type of paper. Assume you are using an old word processor that is not online, but is instead a program on your computer. You write the paper and decide that it needs a lot of work. Instead of editing the document directly, you make a copy and work on that document. This way if you really mess something up, you can just delete the copy and start over. When you are done with this copy and you like the changes, you may manually copy in the changes you like, or if you like all the changes, just get rid of your old version and use this new version as your paper.

This example is similar to how a Git branch works. You are essentially making a complete copy of your repository so you can work on new features, fix bugs, or keep different versions of your code. There are two common ways that I have used Git branches in the past.

Git Development Branch

The first and simplest way is to have a development and a master branch. All your new features are developed on the development branch, and when you have everything working and ready on the development branch, you merge the development branch into the master branch. This way you keep your master branch as the true “production level” code, while keeping a development branch to build new features and fix bugs on. This is a useful way to get started; however it starts to break down when you have a number of developers working on the same
branch at the same time.

In the diagram above, a copy of the master branch is made by creating a development branch. Development is then completed (each circle representing a Git commit). When the development is finished, the development branch is merged in with the master branch. In this model, the Development branch is always kept open.

Git Features Branch

The second way (and my preferred method) is to use Git branches to develop new features, or fix bugs. This is actually really simple if you take a second to think about it. Any change that you want going into the master branch (production/live code) must first originate as its own unique Git branch. If you need to fix a bug, you create a new branch to fix that bug, and when it’s ready, merge it into the master branch. If there is a new feature to be built, you create a new Git branch, develop the new feature, and when it’s ready merge it into the master branch. If you are working on just one thing at a time, this may seem like a little overkill. However, imagine you are working on two or three features at one time. Keeping separate Git branches for each feature means you can release one of the features without having to have all of the features completed.

In the diagram above, you can see that there are examples of both a Bug fix branch and a New Feature branch. Development is performed on each branch and as soon as the individual branch is ready, it is merged into the Master branch. The final circle in the Master branch contains both the Bug Fix and the New Feature. Using the Git feature branch process, the branch is closed after it has been merged in with the Master branch. It is important to keep in mind that in this
example you may have a good number of branches open at one time (depending on team size and what you are developing).

Ninja Lesson: If you use some type of project management or task management system (and you should), you can name your branches containing the id number of the task. For example if I have a task to add a newsletter signup form to a website with a task id of 123, I would create my branch and call it 123_newsletter_signup_form to make it easy to track down exactly what it is and why it was created.

There is a third and more complex way. If you are building more complex software with longer release cycles a method known as Gitflow (or various versions of it) can be used. The reason I don’t mention it in more detail is because it is slightly more complex and can lead to longer release cycles for your software. I enjoy having the ability for myself or the developers I work with to be able to make a change and have it released on the live website in the same day (sometimes in a matter of a few hours). This keeps the process lightweight and simple. In most
cases with websites you do not want long release cycles and instead want the process of getting something launched on the live site to be managed but not difficult.

Let’s look at the paper example again. You could email your paper to a friend for editing. Your friend would make some changes and suggestions and send it back to you. You would then decide which changes you want to keep and those that you are not going to use. In this example, think of your paper as the master Git branch. Your friend gets a copy (a new Git branch), makes some changes (some Git commits), and requests that the changes be merged in (a Git merge request). Now that you understand the basic concepts, we are ready to try out a few real examples.

Creating a Git Branch

The first step to learning how to actually implement Git branches is to create your first Git branch. In the following examples, we will go through the process of implementing a new branch to build a new feature. We will just use simple text files, but you should be able to easily see how it can be used with your code.

Git Command What does it do?
git branch [branch_name] Create a new branch (copy of the code) to use to develop a new feature or fix a bug.
git branch Lists all of the available branches

To create your first branch called my_new_feature, we just run the git branch my_new_feature command.

Git Create New Branch

In order to see all of the available Git branches in your repository, you can run the git branch command.

Git Branch Command

Notice in the example we have two branches, one called master and one called my_new_branch. The * character indicates the branch we currently have checked out. Any new commits we make will be on the currently checked out branch.

Checking out your Git Branch

Now that we have the branch created, we need to checkout the branch in order to start committing our code changes to it.

Git Command What does it do?
git checkout [branch_name] Checks out an existing Git branch. This simply switches your code to a different Git branch.
git checkout -b [branch_name] Creates a new Git branch and checks it out. This is a shortcut so you do not have to create the branch and check it out using two steps.

To checkout your my_new_feature branch, run the git checkout my_new_feature command. If you run the git branch command afterwards, you can see that you now have your new branch selected.

Git Checkout New Branch

There is also a shortcut command to create a branch and check it out at the same time. You can run the git checkout -b another_new_feature command to create a branch called another_new_feature and immediately check it out.

Git Create and Checkout Branch

Switching back to the my_new_feature branch is as simple as re-running the git checkout my_new_feature command.

Git Checkout Branch

Making changes on your new branch

Making changes on your new branch is exactly the same as before. Simply make the changes, add your changes to the staging area, and commit your changes to your Git branch. In this example we make a small change to a text file, add the change, and make the Git commit.

Git Committing a Branch

Merging a Git Branch

After you make your changes and you have those changes tested and ready to go, the time will come to merge in your changes from your feature branch into your master branch. Again, the master branch is typically the Git branch used for your production level code.

Git Command What does it do?
git merge [branch_name] Merge [branch_name] into your currently checked out Git branch.

The first step is to checkout your master branch using git checkout master, after that you can merge in your my_new_feature branch into your master branch by running git merge my_new_feature.

Git Merging a Branch

Git Branches summary

You now know the basics of branches in Git. This is just the beginning, you will need to learn a lot more such as fixing conflicts and what to do with your Git branches when you are done with them. You will want to spend some time learning and experimenting with Git branches to find the workflow that works best for you. In An introduction to Git (part 5), we'll wrap it all up, learn about Git remotes, and learn how Drupal comes into the picture.

Comments

For the basic git commands I like "ungit". It gives you a simple and clean view of your commits, the changes you've made and allows you to execute the simple commands easily. I find with the command line view you can easily miss things whereas with ungit it's much easier to see things.

I have not tried ungit, but I will give it a try sometime. Looks pretty easy to use. I prefer the command line because I have been using it for so long and know the process very well. However, I know a lot of people that do prefer using a UI because it helps simplify things and make sure things are not missed.

Thanks for the comment.

I really have a lot of difficulty to really understand the use of Git to make changes on my site. I get it for the hardcore coding module development, but for a simple change like adding a blog where 95% of the change are in the database that don't seem to make sense. I know it probably do make sense, but I don't get it for the moment. I know that I have to use Features to transfer the configuration into the code, but that won't save every thing, the contextual blocs and the blog page special configurations won't be saved into the feature.

And if I work in a team and my colleague pulls the new modification from Git that won't tell him that he have to activate the feature to active the blog, and the block special configuration also won't be there.

I'm missing a piece of the puzzle here! I need to see the complete process of making an addition to a site, like adding a full page with content type, view contextual blocks etc. and pushing all those changes to Git. Then push those changes to a staging server and finally pulling those change a apply it a second local development environment to simulate team work.

I know this is not specifically related to branches, but I see the same problem with branches. If I work on "A" branch one day and before I finish I start working on a "B" branch's, the change of the "A" branch will still be on my database when I work on the "B" branches and that may result as a conflict when it's not to my colleague because I didn't work on the "A" branch.

I will stop there, but I still have so much interaction with that...
Anyway, thanks for the good work.

You brought up many good points here. I think this is a struggle for everyone getting started with Git and Drupal. The features module gets you very close but not quite all the way. The Features Extra module might help with your block configuration issues, but blocks are a little trickier to keep track of. Also, make sure you are using the StrongArm module as this will allow you to keep track of the content type settings.

One way my teams get around the developer inconsistency issues is to periodically pull the database from the next environment up. This means if everyone has their own dev environment, there is a stage environment, and there is a live environment, you would pull the database from the stage environment. We have a script that we can run to quickly and easily sync the database (it uses the drush sql-sync command).

The problem with the A branch/B branch should not turn into too big of an issue if you think about how you plan out your feature modules. If the change for A and B are that closely related, then there is a good chance they should be in the same feature. For example, if you are creating a content type, view, and menu link, this won't necessarily affect someone else modifying a different content type or view. There are situations where you might run into this issue, but in those cases you might have to solve the problem with some communication with the other developers on your team.

It's far from perfect, but if you spend some time getting the processes down and setup correctly, you can save a lot of time and increase your efficiency quite a bit.

Post new comment