Last time I created a local Git repository, in which I could have several svn/ prefixed branches and one master which is linked to the remote trunk.
Working with Git is quite different to using Subversion. The actual contents of the project directory change to reflect the currently active branch: the directory contains a whole repository, not a checked out copy. Don’t get alarmed when files start disappearing only to reappear again when you switch branch.
I also noticed that I interacted with the version control less frequently when editing, delete, and create files. The interaction is saved until you’re ready to commit, making the process feel more seamless. I occasionally used to get into trouble by deleting files via the OS, rather that using the Subversion command.
For the majority of the time, I’ll use the Git commands, as I’m working in a Git repository. The git svn functionality is only needed as a Git interface with Subversion.
I like the master branch to always reflects the current trunk until I choose to update it, so all my commits are made from other working branches.
I start by checking out a branch based on master to use as a base from which to work. I’ve imaginatively called it basework in this example, and as a branch of master it is linked to the same remote branch: trunk.
git branch -a
should display all your branches in the repository.
jkw@mac> git branch -a
* basework
master
svn/trunk
jkw@mac>
I work in increments based on stories, that’s another post, so I actually create a story branch from basework, that can be merge back into this parent upon completing the story. This helps cope with changes in the remote codebase.
It’s a good idea to check that basework is up to date with the remote Subversion trunk before branching:
git svn rebase
This will either update the local repository with the remote changes, or tell you that the current branch is already up to date.
I’m now in a position to create my story branch:
git checkout -b inwork
The -b option is used to create a new branch and then switch to it. Without this option the same command is used to move between branches.
This same process was used to create basework.
I have my working repository structure, and I’m currently working on my story branch, see the asterisk.
jkw@mac> git branch -a
basework
* inwork
master
svn/trunk
jkw@mac>
You can see details of the changes to the local working branch using the git status command:
jkw@mac> git status
# On branch inwork
nothing to commit (working directory clean)
james@cybermac1> git st
# On branch inwork
# Changed but not updated:
# (use “git add/rm
# (use “git checkout —
#
# modified: footer.php
# deleted: images/feed-icon-64.png
# modified: style.css
#
# Untracked files:
# (use “git add
#
# includes/category-1.inc.php
no changes added to commit (use “git add” and/or “git commit -a”)
jkw@mac>
To add the new file show in the example to those being tracked:
git add includes/category-1.inc.php
If I wanted to add all of the untracked files, I could use the -A option instead of individually naming them.
Now all the files are staged, the time comes to commit them to the local Git repository:
git commit -a -m "A message to describe the changes."
Leaving the -m option off will cause Git to request comments using whichever editor is defined in your configuration files.
I now the story is complete, and all the changes committed to the inwork branch, it’s time to commit them to Subversion.
I start the remote commit process by switching to the basework branch:
git checkout basework
Next I check that the remote codebase hasn’t changed, or update the changes:
git svn rebase
I’ll merge inwork into basework:
git merge inwork
I use my text editor to manually fix conflicts that arise. Git tells you where to find them by marking up the code. This is followed by another local commit, at which point the merge is complete.
Now I can try a dry run of the remote commit:
git svn dcommit -n
It’s the -n option that makes this a dry run: nothing has been committed yet. It shows you the local versions to be bulk committed if you choose to go ahead. To actually perform the commit, remove the -n, and re-run the command, it may take a while if you’ve been busy.
This is where leaving the master branch untouched pays off. basework has been committed to the remote trunk, whilst master still reflects the pre-commit trunk.
I switch to master, which should contain none of my new work, and update it from the remote trunk:
git svn rebase
It should have changed to match basework, and if so the previous commit worked.
I’ve verified the commit: I have master and basework branches that are identical, so inwork is no longer needed, I’ll delete it:
git branch -d inwork
Deleting a child branch of a different parent is a little dangerous, so if you’re not in basework you’ll get a warning. Either switch to basework and try again, or re-running the command with the -D option.
If I’ve finished work on this project, I’d delete the basework branch too, but if I’m going to continue, I’d use it to create another working branch, and I’ve gone full circle.
There are no comment for this post at the moment. Please feel free to let me know what you think.
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.