Jabberwocky

This site is work in progress ...

Fscking up with git and how to solve it

March 24th 2010

I've been using git for nearly two years now, but this job is the first time I'm using it with more than 2 people on the same project. And it's different, I can tell you.

In this case you need a workflow: we adopted this one, also described here.

It's a good workflow. But human error means that you can go wrong.

Forgetting to branch

The workflow demands that you do all your work on branches - that way you avoid merges on master, and can maintain a nice straight and clear master branch. But, as you start working on a new feature, you might forget to do that git checkout -b boldly_go And start coding and committing on your local master. What now ? Well, git offers an easy solution. Tag your latest commit (give it a label)

git tag boldly_go_tag
      

reset the master to its remote position (do not use --hard or you will lose your work)

git reset --soft HEAD
      

create a branch out of your tagged commit, which is not on any branch just now

git checkout -b  boldly_go boldly_go_tag
      

Better:

git checkout -b boldly_go
      

to create the branch

git checkout master
      git reset --hard origin/master
      

to reset the master to its original position.

My last commit message lacks poetry

Or I forgot to add this one file. Solution:

git commit --amend
      

Forget I ever did that last commit

Careful, this will remove any changes you added in that commit. This will only work locally, of course:

git reset --hard HEAD^
      

if you want your commit to go away, but your code to still be around:

git reset --soft HEAD^
      

Going off the map

As you work on your branch, you want to do regular rebase with the remote master, to minimize any later merges and avoid surprises. After every commit:

git checkout master
      git pull
      git checkout boldly_go
      git rebase master
      

Here's where you can go very, very wrong: as long as you're in rebase state, you're in a situation where you're NOT on a branch. So if after a coffee break you forgot you're in rebase, and you continue working, you're working into the void !!

$> git branch
      *(no branch)
      boldly_go
      master
      

If you then try to do a rebase again to get up to date with master, you won't find your commits where you expected them. Oh noes ! Where did my work go ! No panic (to be honest, i did panic a little): git keeps all your commits. You can find them in the .git/objects directory, if you care to have a look. What you just did is create a 'dangling commit', that is a commit unlinked to any branch. Fortunately, there's the aptly named git fsck command.

git fsck | grep commit
      

(the grep commit helps separating the commits from the other dangling stuff) then use the SHA associated with your commit to create a tag:

git tag sos 9a4e6286aa2e2bd97334ad35b555169c2d3033b4
      git checkout -b not_so_bold_now sos
      

this creates a branch based on the tag, and you can continue working.

another good one to know in that case is

git reflog
      

this shows all commits, dangling ones included, with their message, making it easier to find the commit you're looking for. Same procedure for the rest.

This and many other tips, and sources, can be found on git-ready. Thanks to Alain Ravet for some of the tips :)

blog comments powered by Disqus