Our Git branching strategy may seem a little technical initially, but it is actually straight forward once you understand it.
We use the Integration Manager Workflow to manage our GitHub branching and merging strategy.
The Integration Manager Workflow is a workflow that is basically inherent in GitHub. The IM workflow is based upon the practice of multiple repositories:
- One central repository (or the “Blessed Repository” in Git terms) with write access only by the integration manager
- One repository per developer – to share the developers code
In this scenario, you create a fork of the Warewolf repository on GitHub. The Fork is your remote repository. You can then clone your repository to your local workstation and use your local repository to develop within before pushing their changes back to your forked repository.
The Integration manager is then responsible for merging the developer changes back into the blessed repository, from their remote repositories.
This walk through starts at the point, where you have cloned your own remote repository (your Warewolf- fork). The UML diagram below shows the typical use case where you as the developer fulfil two main tasks:
- Get changes from the main (blessed) remote repository and
- Send your changes to your own remote repository to make them available to other developers and, in particular, to the integration manager by a GitHub pull request.
It is then the Integration Manager’s responsibility to merge your changes back into the blessed repository.
Setting up Your Git Config file
Your local cloned repository has a config file located in the .git folder. The config file has a section called [remote]. This section can contain 2 URLS,
- The source URL pointing to the Blessed Repository
- The PushURL to your Fork.
Your [remote] section should look like this:
[remote "origin"] url = <a href="https://github.com/Warewolf-/Warewolf-.git">https://github.com/Warewolf-/Warewolf-.git</a> pushurl = <a href="https://github.com/[MyUserName]/Warewolf-.git">https://github.com/[MyUserName]/Warewolf-.git</a> fetch = +refs/heads/*:refs/remotes/origin/*
This default configuration will enable you to push and pull to different repositories.
A branch is a separate line of work. You may have seen these before in other VCS’s, but in Git they’re so easy to use that they’re addictive and life-altering. You can expose branches in the public repository (a public branch) or they may never leave your workstation (a topical branch).
- A public branch is one that more than one person pulls from. In our Warewolf- repository the branch that you will pull from is the development branch which is a public branch.
- A topical branch (or feature branch) is a private branch that you alone are using, and will not expose in the public repository. Topical branches are used by you to manage your own development process.
- A tracking branch is a local branch that knows where its remote is, and that can push to and pull from that remote. Assuming a remote named “origin” and a public branch named “development“, we could create a tracking branch with git branch –track development origin/development, or with newer versions of git, git checkout –track origin/development
How Feature Branches Work
The Feature Branch Workflow still uses the central repository, and master still represents the official project history. But, instead of committing directly on their local master branch, developers create a new branch from their development branch every time they start work on a new feature. Feature branches should have descriptive names, like animated-menu-items or issue-#1061. The idea is to give a clear, highly-focused purpose to each branch.
Git makes no technical distinction between the development branch and feature branches, so developers can edit, stage, and commit changes to a feature branch just as they did in the Centralized Workflow.
In addition, feature branches can (and should) be pushed to the central repository. This makes it possible to share a feature with other developers without touching any official code. Since master is the only “special” branch, storing several feature branches on the central repository doesn’t pose any problems.
The fundamental idea of rebasing is that you make sure that your commits go on top of the “development” branch that you “rebase” them so that instead of being related to some commit way back when you started working on this feature, they get reworked a little so they go on top of what’s there now.
Don’t do your work on the public branch (Don’t work on origin or development). Instead, work on a “topical” or “feature” branch, one that’s devoted to what you want to do.
When you’re ready to commit something, you rebase onto the development branch, plopping your work onto the very tip of the public branch, as if it were a single patch you were applying.
Here’s the approach. We’ll assume that we already have a tracking branch development for the public development branch.
$ git checkout development # Check out the "public" branch $ git pull # Get the latest version from remote $ git checkout -b myBranchName_101026 # topical branch with ticket number at the end. .. # do stuff here.. Make commits.. test... $ git commit -a -m "Comments on my changes" #commit changes to your topical branch $ git fetch origin # Update your repository's origin/ branches from remote repo $ git rebase –i origin/development # Plop our commits on top of everybody else's $ git checkout development # Switch to the local tracking branch $ git pull # This won't result in a merge commit $ git rebase –i myBranchName_101026 # Pull those commits over to the "public" branch $ git push <a href="https://github.com/MyGitUserName/Warewolf-.git">https://github.com/MyGitUserName/Warewolf-.git</a> #Push the public branch back up, with my stuff on the top to my fork
The fundamental idea here is that I as a developer am taking responsibility to make sure that my work goes right in on top of everybody else’s work. And that it “fits” there – that it doesn’t require any magic or merge commits.
Using this technique, your work always goes on top of the public branch like a patch that is up-to-date with current HEAD. This is very much like the CVS patch workflow, and results in a clean history.
Merging and Merge Conflicts
Any time you do a rebase, you may have a merge conflict, in which Git doesn’t know how to put your work on top of the work others have done. If you and others are working in different spaces and have your responsibilities well separated, this will happen rarely. But still, you have to know how to deal with it.
Every OS has good merge tools available which work beautifully with Git. Working from the command line you can use git mergetool when you have a conflict to resolve the conflict.
Using this workflow, you will end up with all kinds of redundant and abandoned topical branches.
From time to time, you can clean them up with
$ git branch -d myBranchName_101026
or, if you haven’t ever merged the topical branch (for example, if you just used it to prepare a patch
$ git branch -D comment_broken_links_101026
Not what you were looking for? Ask our expert users in the Community Forum.