Archive

Archive for the ‘Git’ Category

My Git – Svn Workflow

April 26, 2010 Leave a comment

Since updating msysgit to 1.6.5.1, I have been able to drop the custom cherrypick script I was using to commit back to my subversion repository and finally use the “proper” git – svn workflow. I’m writing it up here because every so often I forget bits of it.

My usual development workflow is based around doing all development in a topic branch.

1.  Ensure master is up to date
      -  git svn rebase
2.  Create a topic branch and switch to it
      -  git checkout -b [topic branch]
3.  ... write some code ...
4.  Commit to local git topic branch ( I use git extensions usually )
      -  git add .
      -  git commit -a -m [commit message]

When I have completed developing a feature and need to check it in to the subversion repository, I use the following workflow:

1.  Ensure master is up to date
      - git checkout master
      -  git svn rebase
2.  Rebase the topic branch to master - this ensures your topic branch is a
 continuation of the current master branch and will fit better with subversions
 linear "view" of the world
      -  git checkout [topic branch]
      -  git rebase master
3.  Merge the topic branch onto the master - because of the rebase in the
 previous step creating a common ancestor, this will be a fast forward merge
      -  git checkout master
      -  git merge [topic branch]
4.  Commit to the subversion repository
      -  git svn dcommit
5.  Delete the topic branch ( assuming that the dcommit was successful,
if the dcommit failed DO NOT delete the topic branch )
      - git branch -D [topic branch]

Sometimes msysgit barfs, usually when committing a large number of local commits to subversion. To fix a broken dcommit, resync the subversion master and topic branch repositories and continue with the dcommit as shown below.

1.  Clean up any staged / unstaged files left by the broken dcommit
      -  git checkout master
      -  git reset head --hard
      -  git clean -d -f
2.  Ensure the master is up to date with the subversion repository
      -  git svn rebase
3.  Resync the master and topic branch
      -  git checkout [topic branch]
      -  git rebase master
4.  Merge any remaining changes onto master
      -  git checkout master
      -  git merge [topic branch]
5.  Resume committing changes to the subversion repository
      -  git svn dcommit
Categories: Git

Showing commits not yet on master

August 27, 2009 3 comments

I use git most days now, it means I can work on my laptop and commit back to our subversion repository when I am connected again ( or when I finish working on the feature ).

As I have posted previously, I cannot dcommit multiple commits – git freaks out and makes a mess of things after the first commit. To get around this, I do all my work on a topic branch and then cherry-pick the commits from the topic branch into master and dcommit each one individually.  While this works, it is painful so I am slowly working out how to get the list of commits and cherry-pick then dcommit them individually by stringing a bunch of commands together.

The first thing I need to do is get a list of the commit hashes that need to be cherry-picked from the topic branch.


git checkout master
git log master..<topic_branch> --format="%h" > commits.txt

This gives me a nice list of commit hashes that I can use to issue the cherry-pick commands. Beware – at this point the list is in inverse commit order – that is, the oldest commits are at the bottom of the list.

I will keep updating this post as I get closer to having a single command that I can issue to mimic the following ( that I can use due to some weird error )

git checkout master
git svn rebase
git rebase <topic_branch>
git svn dcommit
git branch -D <topic_branch>

Update … with very little research and effort I have managed to create a bash script that mimics the workflow above.
The following bash script gets a list of the commits that are on the topic branch but not in the master in chronological order oldest first and replays them onto the master, one commit at a time, dcommitting the changes between each commit. Ironically, while I was researching / writing this script I may have found the solution to my issue – git svn dcommit --no-rebase.


#!/bin/bash
echo `git checkout master`
echo "Rebasing against remote svn repository"
echo `git svn rebase`
for commitHash in `git log master..$1 --reverse --format="%h"`
do
echo "Merging next commit"
echo `git cherry-pick $commitHash`
echo "Commiting changes to remote repository"
echo `git svn dcommit`
done
echo "$1 successfully merged and dcommitted - don't forget to delete the branch"
exit 0

The script can be put anywhere that is on the bash path – I currently leave it in the root of the folder I am working in ( same folder that houses the .git folder ). Calling the script is as simple as dcommit <topic_branch>.

Categories: Git

Fighting with git svn

August 25, 2009 1 comment

First up, a disclaimer – I am a git n00b therefore anything below may or may not be correct but “it works for me” so I am putting it out here for anyone else facing similar issues ( and also for future reference as I have a feeling this will happen a few more times yet ).

I have recently moved to using git on my laptop. Originally I installed GitExtensions ( which uses msysGit 1.6.3 ), but after some problems I uninstalled that and installed msysGit 1.6.4 using this excellent guide from Jason Meredith.

I cloned the repository I was working from using:

git svn clone https://<server>/svn/<projectname>/trunk

I didn’t need all of the branches so I only grabbed the trunk. My upstream repository is a subversion repository hosted within Visual SVN Server 2.05.  After cloning the subversion repository I wanted to work on, I started working as usual with the following workflow:


git checkout -b
... work work work ...
git commit -a -m ""
... more work / commit cycles ...

Once I had completed the task ( integrating the spark engine as it happens – what a joy to work with that is ), I jumped back to the master to commit my changes back to the upstream repository. I rebase the changes from my topic branch onto the master so that I end up with a linear commit history that doesn’t confuse git svn.


git checkout master
git svn rebase
git rebase
git svn dcommit

And this is where the trouble started. git svn completed the first commit of 4 and then decided there were no more changes between current head and refs/remotes/git-svn so it reset to the latest refs/remotes/git-svn and left me with a number of unstaged files that made up the changes for the remaining 3 commits. Poking around with git log showed me that git still had the commits in master but I could no longer dcommit them due to git and svn being out of sync.

To clean up git I reset master to the last committed svn revision and then removed all of the git commits after that using a combination of git svn reset -r , git reset –hard and git clean -f ( I can’t remember the exact sequence of commands so I won’t post them just yet ). Once I had both git and git svn synchronised back to the point of the last commit, I cherry picked each commit from the topic branch and dcommitted them one at a time to the remote subversion repository:


git checkout
# Use this to get the sha1 commit tags of the commits to cherry pick
git log
git checkout master
# Repeat the following for each commit on the topic branch that needs to be dcommitted
git cherry-pick
git dcommit

This is essentially the same as git rebase / git svn dcommit except you are pulling the commits one at a time.

While I still don’t understand why git svn dcommit refuses to work for multiple commits, at least I can continue using it to work offline, although I think I’ll be using git merge –squash going forward.

Categories: Git
Follow

Get every new post delivered to your Inbox.