Sometimes in Git we will do a merge that will need manual intervention.
If you are merging your own stuff in with your own stuff then most of the time you are going to know which bit of code to keep or if to keep them both.
Things get interesting when either of the following two cases apply;
- You are merging in someone else’s code
- You can’t remember why you had written the code that is causing the issue.
Both of these cases can be solved by a using git’s blame.
git blame will show you a line by line breakdown of who wrote what line of code and as part of what commit and why this is useful for helping with merges is that it will;
- Let you know who you need to contact to discuss what needs to happen with this merge if it is non-obvious.
- Give you a commit hash that you can then query to find out the bigger picture and the context of the smaller change that is currently causing you issues.
git blame on a file simply call
git blame my_file_name.rb and the output will be the contents of the file with each line prepended with the commit hash, the commiter and the the date and time it was commited.
We are so used to applications on our phones and computers shouting at us every two seconds to update them to the latest version that we can become blind to new releases of software that don’t ram the fact they are updated down your throat.
Git is a fine example of this, like most command line tools it will happily sit on whichever version you happen to have installed way back when, and that is fine, except for if you installed Git a year or more ago you might be missing out on some new features and bug fixes.
To find out what version of Git you are running simply type
git --version into your command line, I am going to guess it is sitting at 1.7.x.
As of writing the most recent stable version is 126.96.36.199, if you want to see what the difference is between your version and the current version take a look at this Git Changelog.
How you installed Git will have some influence on how you update it, on OSx I think Git comes pre-installed so what I have had to do in the past is download the .dmg file from the Git website and install the latest version, making sure to add the install location of the new Git to my PATH variable so it is seen as the version of Git to use.
Git branches appear to be case insensitive, which isn’t a problem in and of itself, but if you clone a remote branch from github like this:
git checkout -b my_new_branch /origin/My_New_Branch
Git will see your new branch as
my_new_branch* and when you pull it will check
origin/My_New_Branch which is totally correct and sane, but if you do a push it seems to want to push to a new branch in github called
my_new_branch which will get super confusing if multiple people need to access this branch.
The ideal fix for this is prevention – just don’t create a new local branch with a different name to your remote branch, but let’s say you do?
Creating a new branch with the correct case will not work because git is case insensitive and will see both
My_New_Branch as the same thing, instead you need to rename your current branch using a middle step. Luckily like most things in git this is very straightforward;
git branch -m my_new_branch tmp_branch (will rename your lowercase branch to tmp_branch)
git branch -m tmp_branch My_New_Branch (will rename to your desired CamelCase branch!)
Now your pushes should go to the correct branch.
*Disclaimer – My_New_Branch is a terrible name for a branch, always be descriptive and imagine you are naming it for someone else who doesn’t know the project to read.
Since we are all using version control these days, or should be, then perhaps it is time for a development process that sits before TDD or whatever process you generally like to do.
I am calling it Commit Driven Development.
So the normal process is you write your code, you test it, build it, etc and then you think about committing it, if you are anything like me then the commit message will be build up of things you remember as you look through the files currently sitting in the staging area. This is probably a little backward by today’s standards.
What if instead we start by writing our commit message, a succinct note of what we want our next chuck of development to accomplish and we work on that until the commit message captures what we have in our code.
As well as helping us plan our time a little better, I would imagine that doing this will help focus our development, because doing anything outside of that commit message would not longer make sense and we would (hopefully) get away from doing it.
Often I have found myself in a situation where it would be really nice to have an archive of the files I have recently been working on.
Using two Git commands I can easily create such an archive.
The first actually creates the archive;
git archive -o update.zip HEAD
This will create an archive of the entire repository, which isn’t what we want in this instance but is pretty handy to know.
The archive function accepts a list of files to archive, which is what we want to do and is where our second command comes in.
git diff --name-only HEAD^
This will do the commit before the head, which is what I want most of the time but this could be changed to get files between two commits or anything you wanted, check out the help section in git for the diff command.
Finally we want to bring this all together into one nice and easy command, thus;
git archive -o update.zip HEAD $(git diff --name-only HEAD^)
This wraps our second command with $(), this gets ran first and passes the result as a parameter into our first command.