The branch part of the following is based on A Git Workflow for Agile Teams, which also contains lots of other useful links.
For any project you want to work on you should create a fork in GitHub, by clicking on the 'Fork' button on the project you are interested in.
From now on we'll call the project you have forked from upstream
and your own copy of that project on GitHub we'll call origin
.
If there is no entry in Lighthouse for the card you are about to work on, then create one. In the body of the ticket put a short description of the feature and then the acceptance criteria. An example is ticket 213.
All work on bugs or features should take place in a branch within your fork. This makes it easier for people to pull your code, independent of other work that is in progress...including your own! (Since you will be starting work on something new before the last thing you worked on is deployed.)
To get started on a new feature or bug-fix, create a new branch based on an issue in Lighthouse or Pivotal Tracker. Say the issue is 211-allow-users-to-login-using-a-linkedin-account
, then create a branch that is based on master
, as follows:
git checkout -b 211 master
You will now have a branch called 211
. If at some point you also start work on 213-implement-company-revewvoting
you can create another branch to hold that work:
git checkout -b 213 master
Note that this branch is taken from master
again, and not from 211
since we want to make it easy for the person merging your changes back into the upstream repo to see what's new.
To move between your pieces of work simply checkout the branch you want, work on it, and commit your changes:
git checkout 213
# work on file1
git add file1
git commit file1
You'll need to have a clean working directory (i.e., all changes committed) before you can switch to another branch, but if you desperately need to flick over to another branch to make a quick change then you can stash your changes away temporarily:
git checkout 213
# work on file1
git stash
git checkout 211
#work on file2
git add file2
git commit file2
git checkout 213
git stash pop
Make sure you commit your changes often (using Tim Pope’s git commit message best practices). You don't need to worry about how many commits you make since when your code is finally merged back into the upstream repo your entire work will become a single commit. This means that you can use commits to help you remember what you changed, try experiments, and so on.
Whilst working on a branch be sure to rebase frequently. Rebasing involves undoing all of your changes, pulling in any changes that have been made since you started work, and then reapplying your changes on top. Doing this periodically ensures that your code will blend correctly with other code that is being committed by other developers.
Performing a rebase is simple, since Git will do all of the complicated work for you. First fetch any changes that have been made to master
in the main repo:
git checkout master
git pull upstream master
Whilst you're here you might as well update the master copy of you fork, up on GitHub -- that way its master
branch is always in sync:
git push origin master
(Note that we 'pull' from upstream
but we 'push' to origin
.)
There shouldn't be any merge conflicts because you should never be modifying master
(to put it another way, you should only ever get 'fast-forward' merges). Now you can rebase your branch against these changes:
git checkout 213
git rebase master
There will be a number of occasions where you either need to push your code to someone else, or pull in code from someone else. For example:
- you've finished working on a feature, it has been tested, and you now want to see it deployed;
- someone else has finished working on a feature, and they want to see it deployed...and it's your job to integrate the code;
- you and someone else are both working on the same feature and you want to share code with each other as you go.
When you've completed the work you are doing, and it's ready to move to the next stage, you need to let someone know that your code is ready. If the project is an internal one then in Lighthouse set the milestone to Test
and make the responsible person markbirbeck
. If the project is a public one then issue a pull request. To do this, go to their fork on GitHub and press the pull request button. GitHub should work out which revisions you are offering and help you prepare the request.
Whichever way you do it once you've fired off your notifications you can get on with other work, until you get some feedback from whoever you passed the code on to.
If you are in the position where someone has modified code on your repo and would like you to accept their changes, then you may receive a pull request. If you are just sharing code with someone (perhaps you're both working on the same feature) then you can use the simple GitHub merge interface.
However, since this brings in the entire commit history for the new code we don't use this technique when merging back to the main repo. Instead we pull the changes in as a single package.
First, if you are going to be dealing with the same downstream repo a lot, add it to your list of remote repos:
git remote add atchai [email protected]:johngriffin/level-theme.git
Next create a branch to pull the changes into (you may already have this branch if you are also working on the same thing). First we ensure that our master
branch is up-to-date:
git checkout master
git pull upstream master
Then we create a branch to hold the new changes:
git checkout -b 209 master
Now merge the downstream branch into your new branch, and rebase off master:
git pull atchai 209
git rebase master
You now have a branch that contains the other person's work on the ticket, possibly in addition to your own work on the same feature.
If the branch is now complete, we need to merge it to master
. First make sure you're on master
:
git checkout master
Now merge the branch in question into your working directory, but reduce -- or squash -- all commits to a single commit.
git merge --squash 209
We now have all of the changes in the working directory, ready to be committed. We could modify them further at this point, if we needed to. Once everything is ready then the final step is to perform the commit (with appropriate attribution):
git commit --author johngriffin
(The author parameter should be set to a string that will be used to 'find' the full author name and email address from previous commits.)
You'll get a commit message to edit which contains all of the rolled-up commit messages for the revisions that have been squashed, and you can select and rearrange those as you wish, to make up your single commit message. Also, if you are committing to the upstream repo then you can add Lighthouse-related comments, such as:
[#209 tagged:committed responsible:markbirbeck milestone:Test]
This causes GitHub to pass triggers through to Lighthouse, which in this case will notify 'markbirbeck' that the milestone has been changed to Test
.
An example of an appropriate commit message is in the commit for ticket 209, and the effect it has on Lighthouse can be seen towards the end of ticket #209.
Don't delete your branch until the issue has been closed in Lighthouse, which will indicate that your code has been merged into the master repository. The normal command is:
git branch -d 209
However, if you modified the branch when making the commit to master
then Git may not realise that all of the changes have bee incorporated. If you get an error message then it's ok to override this with:
git branch -D 209