Git

From Smop.co.uk

Jump to: navigation, search

I've used RCS, CVS, Subversion in anger, but not been very happy with them since I want a distributed system. So it's time to start using git. However until I do that, some links will have to suffice!

I hope to use git in several ways:

  • my personal repository (that's the easy bit)
  • importing my old CVS repository (also pretty easy)
  • migrate work's repository over to it
    • this is hard since I need to provide SVN access to the developers
  • selectively synchronise with SVN repositories
    • the really hard stuff

I often use reuse scripts all over the place - at home, work and for customers. I don't want to lose the revision history (and the copyright status is an orgothonal issue). I also don't want to have to spend any time doing this bar the initial setup.

Let's see what happens.

Contents

Subversion integration

As a developer I've rarely needed to use branches - in fact for what I intend to use git for, I'm happy only tracking trunk. That may change in future, but hey.

http://git.or.cz/gitwiki/InterfacesFrontendsAndTools presents us with two tools:

  • git-svn - this allows us to sync with a subversion repository - pulling and pushing changes to it. It works both for a simple trunk only case and trunk/brank/tags style repositories
  • git2svn - not brilliantly documented, this allows you to import git repositories into subversion

Setup

Git has no concept of a "master" repository - if you clone my repository then yours is just as good as mine. In any case, for the code I work on I'm going to declare my git repository the "master". The reason for this is that I make most changes and I possibly want to sync with two subversion trees - if that's happening then I really want to be able to push changes out and not worry (ATM) about pulling changes back. With git-svn I could pull changes back pretty easily, but I suspect only from _one_ tree.

One issue I'm not sure how to solve is what to do about files I do not wish to be shared - e.g. sensitive information that should only belong in one repository or another. I may just end up having to leave those out of version control and just back them up.

Hugo suggests "svn:externals", but that puts the complexity on the remote repositories (where I'd rather it was hidden) and also only works on directories, not files. I think I can do this using git-ignores from a "don't pull client files into git" point of view (unless git-svn overrides that), but I suspect that a push will send and git commits over.

Repositories

I'll be creating several sites:

  • central site on my server
  • edge site on my laptop
  • edge site on my desktop

There will also be four repositories at each site:

  • scripts - scripts for all sorts (probably publically accessible)
    • will have subdirectories - bin (for ~/bin style scripts), er, not sure what else
  • home - my home directory (which used to work wonderfully in the good old days, but with gconf etc it's not as good anymore)
  • puppet - my puppet configuration (probably private I'm afraid)
  • work-... various other ones from project work (private)

Branches etc

Git has a repository (in ".git"), checked out code (everything not in .git) and finally staging (code you’ve told git you will be adding to the repository (this is noted in .git). Imagine you have created two files - apple and carrot and run “git add apple”. “git diff” shows the difference between current and staging - it will say “carrot”. “git diff –cached” shows the difference between staging and committed files - it will say “apple”. I do wish there were a bit more explanation of this sort of thing - what HEAD is (or FETCH_HEAD) for example is a bit scattered.

Notes

Mostly from these notes

On server:

  • mkdir git/home
  • cd git/home
  • git --bare init
    • you can only "push" to a bare repository

On laptop:

  • git clone ssh://git.smop.co.uk/~/git/home home
    • should be able to drop ssh:// as it's the default
  • git add (files)
  • git commit (or commit -a to automatically add the files)
  • git push

Branches now look like (git branch -a):

  • *master (local repos)
  • origin/HEAD (alias to upstream)
  • origin/master (alias to upstream)
    • master is master branch, HEAD is checked out branch (normally master) at remote - see here

On laptop:

  • git status (show what has changed)
  • git add (add files to staging area)
  • git diff (show difference between filesystem and staging)
  • git diff --cached (show difference between staging and commited)
  • git commit
  • git add foo (oops, forgot a file)
  • git commit --amend (add forgotten file to last commit and change commit message)
  • git diff origin . (compare origin to us)
  • git push

This was causing much confusion - back on the server the checkout version would be inverted - i.e. if I had pushed a new file, the server would say "you have an uncommitted deletion of that file". Basicallly, "public" repositories (ones you are pushing to in particular) should _never_ have any checked out files - they should be so called "bare" repositories with just the .git directory.

Personal tools