Git Workflow
Git Workflow
Conventions
origin: the orig inal remote repository
master: something like the trunk f or SVN, the end of the current tree
HEAD: the tip of the current branch
General workflow
When creating a new GIT repository a branch develop should be created f rom the master.
This is done by running :
git checkout -b develop master
When developing on a new f eature (which should have its own JIRA number) a branch with
the JIRA name&number should be created f rom the develop branch. An example of this:
git checkout -b DHDAPPS-666 develop
Feature branches
Every f eature should be developed in a new branch which can be pushed back to the central
repository. Instead of branching f rom master, f eature branches should use a separate
branch named develop by convention.
Creating a f eature branch named myFeatureBranch f rom the develop branch:
git checkout -b myFeatureBranch develop
Merg ing the changes on the f eature back into the develop branch:
git
git
git
git
checkout develop
pull origin develop
merge myFeatureBranch
push origin develop
Release branches
Maintenance branches
Whenever there is a problem with a production release, when we have opened bugs,
incidents or other issues, then we have to make some patches f or the production release.
Depending on the situation these can be also be called hot-f ixes.
Assuming we have an issue in JIRA named DHBUG-666 the f ollowing should be the steps to
Conflicts
Like with SVN or other similar tools conf licts can appear when merg ing one branch into
another. Bef ore someone can publish his/her f eature they need to f etch the updated
central commits and rebase their chang es on top of them.
If local chang es directly conf lict with upstream commits, Git will pause the rebasing process
and g ive you a chance to manually resolve the conf licts.
When you try to push your changes back to the develop branch f or example and you have
not pulled the latest changes f rom the branch GIT will ref use the request with some kind of
an error messag e:
git push origin develop
error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch
is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git
pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for
details.
The rebase option tells GIT to move all the commits in the current branch to the tip of the
develop branch.
Rebasing works by transf erring each local commit to the updated branch one at a time.
This means that you catch merge conf licts on a commit-by-commit basis rather than
resolving all of them in one massive merge commit.
If conf licts happen while merging two branches GIT will pause the rebase at the current
commit and output the f ollowing message and some instructions on what to do:
CONFLICT (content): Merge conflict in <some-file>
Once you are done with the f ile and it is ready just do:
git rebase --continue
And thats it, af ter this point, GIT will move on to the next commit and will repeat the
process if f urther conf licts emerge.
There is also a panic button in case thing s go too bad and you want to revert everything.
Just run the f ollowing command and youll be back at the start:
git rebase --abort
Scenarios
Working on two separate features in
parallel
Scenario: Two small squads are working on two separate f eatures which belong to the
same product.
We will call these:
TeamA and TeamB are working on their f eatures, they create / update / delete f iles, add
them to GIT, commit them (locally):
git add <filename> # stages a file
git commit # commits only the staged files
They can do this as many times as they want because these are local commits without
making it their concern as to what goes on in the main central repository. This can be very
usef ul f or larg e f eatures that need to be broken down into simpler, more atomic chunks.
Next, TeamA has f inished their f eature and now they want to publish it to the central
repository. They can accomplish this by running :
git push origin develop
If the orig inal branch (develop) suf f ered modif ications while TeamA was working on their
f eature then TeamA would f irst need to get the updates:
git pull --rebase origin develop
Now, TeamB will also want to publish their f eature once it is completed. They will try the
same command as TeamA:
git push origin develop
This time it will def initely result in an error f rom GIT because the develop branch was
altered with TeamA merg e:
TeamB will need to run the pull command to get the latest updates:
git pull --rebase origin develop
If TeamA and TeamB added or modif ied the same f iles it is likely that some conf lict will
result while running the above command. When and if that happens GIT wil pause the
rebase at the current commit and output the f ollowing message along with some usef ul
inf ormation:
CONFLICT (content): Merge conflict in <some-file>
Once TeamB has solved their conf licts f or the current commit they have to run this
command:
git rebase --continue
This will instruct GIT to continue the rebasing to the next commit. When and if f urther
conf licts appear in the next commits the process will be reiterated.
If TeamB decides they need to start over or f or whatever reason they want to revert and
not solve the conf licts now they can just run this command to abort the process:
git rebase --abort
When TeamB is f inished with the merging they have to run ag ain the command:
git push origin develop
Next Jim starts his investigation, then proceeds to solving the bug. He f inishes the bug,
adds any new f iles to GIT (if any) and commits them locally:
git add <filename>
git commit
Af ter that Jim is summoned to a meeting. Bef ore going to the meeting Jim asks a member
f rom the QA team to test his solution f or this bug .
Meanwhile Joe came in the of f ice. With a cup of cof f ee on the table Joe decides to check
out if there are any bug s on the JIRA queue. He f inds that there are three bugs and one of
them is marked as In Progress by Jim. He then proceeds and takes the second bug, DHBUG2. Similar to what Jim did, Joe has to create a new maintenance branch called DHBUG-2 and
he has to add new f iles and commit them:
git checkout -b DHBUG-2 master
.....
git add <filename>
git commit
When everything is ready, when the bug is f inished f rom the developing point of view, when
there has been a review made by a colleag ue, when testing was perf ormed (either manual
or automated) Joe will want to integ rate his chang es in the master branch:
git checkout master
git merge DHBUG-2
git push
Bef ore considering the issue to be f inished Joe should also delete the branch:
git branch -d DHBUG-2
Joe is now f inished with his task and happily enjoys another cup of cof f ee.
Meanwhile Jim is f inished with his meeting. He would now like to take the remaining steps
to seeing his bug integ rated back into master. So Jim tries to push his changes:
git checkout master
git merge DHBUG-1
At this point Jim may have some conf licts if he edited the same f iles as Joe. GIT will notif y
Jim of this and when Jim is f inished with the editing he has to do:
git add <filename>
git commit
Jim also must not f orget to actually push the changes to the remote repository:
git push
Jim is now enjoying his work, he has made at least one customer happier.
Jane had a half day of f work and she just arrived. She asked if there was anything to do and
she f ound out that there is one more bug in the JIRA queue. So she decides to take the bug ,
DHBUG-3.
Much like Joe, Jane will not encounter any problems or conf licts because the other two
In addition af ter the release branch is merg ed back into master and develop the new
master should be tag g ed and the release branch should be deleted.
Using a dedicated branch to prepare releases makes it possible f or one team to polish the
current release while another team continues working on f eatures f or the next release. It
also creates well-def ined phases of development, it is easy to say: this week were
preparing for version 4.0 and to actually see it in the structure of the repository.
Release branches should f ollow this naming convention: release-0.1.2 (release-version)
For a release cycle the f ollowing commands should be the most common used:
git checkout -b release-0.1 develop # create the release branch
# solve any bugs that might appear in this release during testing
# update the documentation if the need arises
git checkout master # checkout the master branch
git merge release-0.1 # merge the release back into master
git push # push the changes to the central repository
git checkout develop # checkout the develop branch
git merge release-0.1 # merge the release back into develop
git push # push the changes to the central repository
git branch -d release-0.1 # delete the release branch
git tag -a 0.1 -m "Initial public release" master # tag the new
version
git push --tags # push the new tag
Further considerations
Local vs remote branches
Whenever we checkout a branch we have the latest remote version. However f or the same
branch, we now have a local and a remote version.
When we make some chang e in the branch and we add some f iles and commit them, they
are only commited in the local branch, not in the remote one.
So, running git commit will only commit the f iles to the local branch.
We can have as many local branches as we want, we can commit f iles to any of them, and
they will only exist in the local branch, not in the remote repository.
If we want to send the commits to the remote repository we have to perf orm a git push
on the desired local branch.
If we want to update our local branch with updates f rom the remote repository we have to
either run git pull or a combination of git f etch and git merge (see below a section about
g it pull and f etch).
This creates a new merg e commit in the f eature branch that ties tog ether the histories
of both branches, g iving you a branch structure that looks like this
Git rebase example:
git checkout feature
git rebase master
This moves the entire f eature branch to begin on the tip of the master branch, ef f ectively
incorporating all of the new commits in master. But, instead of using a merge commit,
rebasing re-writes the project history by creating brand new commits f or each commit in
the orig inal branch.
Basically the dif f erence is that git merge will create one large commit with all the changes
in all commits in both branches and git rebase will just create a new commit f or every
commit in the branch making your branch to begin at the tip of the master branch.
The advantag e of git rebase is that we will have a much cleaner and nicer log whereas the
log resulted f rom git merge can sometimes be hard to read.
Git stash
Suppose you are implementing a new f eature f or your product. Your code is in progress and
suddenly a customer escalation comes. Because of this, you have to keep aside your new
f eature work f or a f ew hours. You cannot commit your partial code and also cannot throw
away your chang es. So you need some temporary space, where you can store your partial
chang es and later on commit it.
In Git, the stash operation takes your modif ied tracked f iles, stag es changes, and saves
them on a stack of unf inished changes that you can reapply at any time.
Now, you want to switch branches f or customer escalation, but you dont want to commit
what youve been working on yet; so youll stash the chang es. To push a new stash onto
your stack, run the g it stash command:
git stash
Now, your working directory is clean and all the changes are saved on a stack.
Now you can saf ely switch the branch and work elsewhere. We can view a list of stashed
chang es by using the git stash list command.
git stash list
Suppose you have resolved the customer escalation and you are back on your new f eature
looking f or your half -done code, just execute the g it stash pop command, to remove the
chang es f rom the stack and place them in the current working directory.
git stash pop