Showing commits not yet on master
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>.
This seems like more work than necessary. Trunk should be considered the master. After all, it is tracking your svn repo. I never use the initial master branch.
After you svn init, create a topic branch based on the remote branch (“trunk” if you used -T in init – git-svn if you didn’t – use git branch -a to check or peak at .git/config).
$ git checkout -b topic/a trunk
Do your work.
$ touch newfile.txt
$ git add newfile.txt
$ git commit -m “New file.”
Rebase to bring your topic branch up-to-date with the svn repo, and play your changes on top. Rebase will fetch the latest from the svn repo then perform the topic branch rebase.
$ git svn rebase
Commit changes to svn repo
$ git svn dcommit
Start new topic branch based on trunk.
$ git checkout -b topic/B trunk
Jeff,
Thanks for your comment. I have tried the approach you suggested but unfortunately that does not work either.
I usually clone the trunk as I rarely use svn branches or tags during development ( they are useful for releases etc though but managed via build scripts usually ). The reason I have to do all the extra work is that when I dcommit multiple commits, the rebase between each commit fails. I have also tried git svn rebase / git rebase topic_branch / git svn dcommit –no-rebase and while this does not “unroll” commits, it does still fail when there are multiple commits. The bash script is a workaround that I have to use due to something conflicting somewhere in my system.