I’m still not fully sold on git, but sometimes it’s nice to set up version control for a single project. It’s nice to be able to track what you’ve done, roll back experiments and otherwise protect your work (and sanity.) This is just an annotated account of this process for a small project I was doing with CakePHP, half to later refresh my memory and half for others doing the same.
> git init # create the in-place repo
> git add app # add files
> echo “.gitignore” >.gitignore # ignore some files
> echo “cake” » .gitignore
> echo “.htaccess” » .gitignore
> git branch working # create scratchpad
> git checkout working # start working on it.
Switched to branch “working”
> git status
> git add events_controller.php
> git commit -m”Bug fixes” # commit this set of changes to the working branch
> git diff ../maste # see what you changed
> git checkout master # head back to original
> git merge working # merge your changes in
Recently, I’ve wanted to become aquainted with Git, the open source Version Control System that Linus Torvalds wrote after moving away from BitKeeper. My past SCM experience has been with CVS and Subversion, and the Git model varies significantly. The main difference being that Git is entirely distributed… Essentially, every user has a complete copy of the repository including history and metadata. They work with other repostiories by accepting patches.
If you’ve worked long enough with source code, you’re familiar with patches, probably enough that the network of repostitories connected and synced up by a series of patches described above scares you. It sounds a lot harrier than it ends up being in practice.
For my examples, I’ll walk through the processes I’ve used while working with Io, the neat little language that got me using Git in the first place. Keep in mind, I’m a relative Git newbie and my vantage is that get moving quickly with projects using Git.
git-core package originally, and it was missing some incredibly useful features, git rebase -i being the most important.> git clone git://www.iolanguage.com/Io
Initialized empty Git repository in /home/cdmoyer/foo/Io/.git/
remote: Generating pack...
remote: Done counting 7812 objects.
remote: Deltifying 7812 objects.
remote: 100% (7812/7812) done
Indexing 7812 objects...
remote: Total 7812 (delta 3799), reused 7468 (delta 3566)
100% (7812/7812) done
Resolving 3799 deltas...
100% (3799/3799) done
> git log
...
> git log Makefile
...
> git status
# On branch master
nothing to commit (working directory clean)
steve (it’s already named origin, but when you start to work with multiple repositories, a mnemonic name is helpful). We’ll also use git fetch to ensure that our local copy of steve is still up to date:> git remote add steve git://www.iolanguage.com/Io
get fetch steve
steve/master and master, which is our local copy. We haven’t changed anything, so we won’t see any changes. master is the name automatically given to the branch you checked out and started with. I’ve found it’s best to leave this branch alone, letting it represent the state of steve/master, and use it for merging changes in from other sources. I’ll periodically update master from steve, this is done in one of two ways:> git pull steve
or
> get fetch steve
git merge steve/master
They seem to be synonymous.
At this point, if you’re a CVS or Subversion user, you’re a bit concerned… branches are generally no fun. But under Git, they are pretty manageable. Next we’ll walk through creating a branch, doing work on it, and then creating a patch.
> git branch foo
> git branch
foo
* master
> git checkout foo
Switched to branch "foo"
> git branch
* foo
master
> echo "# a comment" >> Makefile
> git status
# On branch foo
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: Makefile
#
no changes added to commit (use "git add" and/or "git commit -a")
> git add Makefile
> git status
# On branch foo
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: Makefile
#
> git commit -m"Modified the makefile" Makefile
Created commit 14ff3a4: Modified the makefile
1 files changed, 1 insertions(+), 0 deletions(-)
> git status
# On branch foo
nothing to commit (working directory clean)
Note: Locally modified and added files follow you when you change branches, so be careful with files that you modify and leave uncommitted as you move around.
> git checkout master
> git pull steve
> git checkout foo
master, and then apply your changes on top. If there is a conflict, it will drop you to the command-line for fixing any issues.> git rebase -i master
... Uh oh, we had a conflict!
> vi Makefile
> git add Makefile
> git commit Makefile
> git rebase --continue
If we couldn’t fix the merge conflicts, we could do git rebase --abort
> git checkout foo
> git rebase -i master
# generally change all but the first "edit" into "squash" ... you'll see what I mean.
> git diff --color master
> git format-patch master
0001-Modified-the-makefile.patch
> git config user.name Chris Moyer
> git config user.email chris@inarow.net
git diff will only show you changes since your last addition, to see since your last commit:> git diff --cached
> git grep "error"
> git branch -D branchname
Hopefully this will give you enough to get started. It’s server me well so far. As I come across other common, useful or complex operations, I’ll write them up. Good Luck!