Mirroring sipXecs subversion repository with git
From SIPfoundry sipXecs IP PBX, The Open Source SIP PBX for Linux - Calivia
Advantages of creating your git sipXecs mirror
You can keep entire history of ecs project accessible off-line. Your git repo will contain the entire history of sipx project. You will be able to grep any given revision of any file. You'll be able to generate the diffs against any revision, grep the content of any revision or run blame command off-line. All this operations will be a magnitude faster than their subversion counterparts.
You will save disk space: git repository is smaller than subversion working copy and you need only a single repository to keep all your branches.
You can develop a new feature in a separate branch without write access to subversion repository. Git allows to create those branches in a very efficient manner; you can switch between the branches, commit partial work, update the previous commit.
You will be able to easily generate patches to be reviewed and included in sipx official repository. With git it's easy to split your contribution into series of patches: showing history of your changes might make it easier on the reviewer and consequently your patch might be accepted faster. You can maintain and rebase a patch or series of patches against sipXecs mainline.
Installing git
Since git is used by Linux kernel developers it's easyly available on most modern distros. If you use Fedora run this (as root):
yum install git\*
Public sipXecs git repositories
There are several repositories that mirror history sipXecs subversion repo.
They track release branches and trunk (3.10 and master at the moment). Using public git repos is much faster than mirroring subversion directly. Use them, especially if you do not have direct commit access to subversion repository.
Using github is probably the easiest: you can send pull request after publishing your patches. There are guides that describe in details how to do that.
How to create a "read-only" SVN mirror in git
You can skip this part if you decided to use publicly available sipXecs git repository (see above).
The initial clone operation can take several minutes as it imports the entire history of sipXecs repository:
git svn clone http://sipxecs.sipfoundry.org/rep/sipXecs/main ecs
Now you can change to ecs directory and check the status:
cd ecs git status
Git should tell you that you are on 'master' branch
Developing in git repository
Making and committing changes
Note: If you plan on committing changes with git, you need to clone the sipX repository with https, or else you will not be able to commit your changes:
git svn clone https://sipxecs.sipfoundry.org/rep/sipXecs/main ecs
Let's develop a new 'super' features. You should never write new code in master branch. In your mirror repo, 'master' is used only to track subversion mainline. To write new code create a new branch and check it out.
git checkout -b super-feature
Option -b means that you are creating a new branch and checking it out. If you later want to switch to this branch, run the same command without a -b option. 'git checkout' is similar to 'svn switch' (*not* to 'svn checkout').
You can make some changes now
... using your favorite editor
Once you happy with yout changes commit them. You'll be only checking in to your local git repository.
git commit -a
Option -a means that you want to add all changed files to the commit, alternatively you can run git add and add the files one by one or directory by directory. Differently than in subversion, when using git you have to tell it explicitly which files you are committing.
Git is more liberal and forgiving than subversion. You can amend your commit later if you forgot about something. You can even rewrite the history several commits back, as long as you did not share your changes with anyone.
To Check out a specific SVN revision
Find a revision first
git svn find-rev rXXXX where XXXX is svn revision
and then depending on how long you want to use it either copy the first few characters of the tree-ish or tag it or if y want to view it just create a short living branch on it and check it out...
git checkout -b temp-branch b83234
where b83234 is the first few characters of the tree-iss and now you can browse it.
Generating patches
If you do not have write access to subversion sipXecs repository you need to generate patch and ask sipx committers to check it in for you.
Before you generate a patch against master it's a good idea to rebase master against subversion mainline and then rebase your branch against master.
git checkout master # switch to master branch git svn rebase # retrieve the latest commits from subversion repo git checkout super-feature # switch to your feature branch git rebase master # rebase your branch against the master
Git is quite efficient at merging your changes during rebase. Check here about how to resolve conflicts if you have any [not sure where "here" was meant to be, but 'git mergetool' is useful]. Now you're ready to generate the patches.
git format-patch master
Or you can redirect your patches to another directory:
git format-patch master -o ~/patches
Git will generate one patch file for every commit on the branch. Since git lets you to modify the history of the commits you can generate a series of patches that can show the logical development of your feature. Alternatively you can choose to generate a single patch like this:
git diff master > super-feature.patch
You can attach patches to JIRA issues or send them on the list for discussion.
Lets say you have been hacking for a while on a branch (XECS-2387) and your work spans more than one component (in this example, lets say sipXbridge and sipXconfig). You want to commit your sipxbridge changes to svn because you are happy with them but want to submit the other changes as a patch to the owner of the other component because he wants to inspect your patch before accepting it. Here is how to proceed.
git commit sipXconfig/ -m"XECS-2378: sipxconfig changes for supporting hidden parameters" git commit sipXbridge/ -m"XECS-2378: sipxbridge changes for supporting hidden parameters" git format-patch master -o ~/patches # Note that this will create two patches git rebase XECS-2378 master git rebase -i HEAD~3
and remove the line that you want to remove when the editor brings up the interactive screen (i.e. the sipxconfig patch in this case). Then do the svn commit as above. Pick up the other patch and attach it to the issue, thus maintaining friendly relations with the owner of the other component.
Accepting patches sent by other developers
Quite often people will comment on your patches. Sometime developers will generate patches on top of your patch. You can commit them to your git repository.
If someone sends you a patch generated with git
git checkout super-feature # make sure you are in the proper branch git am -3 0005-some-fixes.patch
That will commit the patch to super-feature branch - it will preserve the name of the patch author and their comments. '-3' means that git will try to merge the patch. If there are conflicts use git mergetool to resolve them. You can list multiple commits, or an entire directory full of patches:
git am -3 patches/*patch
You can make your changes on top of the patch and commit them separately. Or you can amend the previous commit with your changes.
... hack ... hack ...hack git commit -a --amend # -a means add all changes, --amend means fix previous commit
You can also easily accept/review pathes generated with svn diff, gendiff etc.
git apply -p0 0005-some-fixes.patch
That will apply the patch but not commit it (if patch was not generated by git it does not have enough information to create commit). It's slightly more convenient than using patch command since it'll behave in an atomic way (the apply will succeed or fail - it won't leave your workspace partially patched)
How to commit your changes back to SVN repository
If you have subversion commit writes you can use git to send your changes back to subversion repository. All additions, renames and deletes will be recorder properly. Subversion commits will not be different from commits made directly with svn client.
Let's say the you have changes in 'super-feature' branch that you want to commit back to subversion repository.
git checkout master # switch to master branch git svn rebase # retrieve the latest commits from subversion repo git rebase master super-feature # makes sure that your branch is rebased against latest version of svn tree git rebase super-feature master # fast-forwards master to include super-feature changes git svn dcommit -n # Check to see what git is about to commit. You can use giggle to look at the changes. git svn dcommit # Actually sends your changes to subversion repo
How to clean up some common mistakes
Git is powerful but its easy to make a mistake. Here are pointers on how to recover from some common mistakes.
Made a mess and did the rebase operations in the wrong order? Don't worry, be happy. The following operation reverses the damage:
git rebase -i yourcommithash^
That takes you to the the one before your commit. That should bring up an interactive rebase screen probably in vi showing all of the commits from yours to HEAD. You can move your commit around in this list. For example, move it to the top, After that, you can
git svn dcommit -n # check your pending commits. git svn dcommit
Say you have this one file you want to replace from svn head. Further, you were bad and committed this file directly to svn without going through git. You want to replace your git copy in master with the svn version so you will avoid committing it back to the svn repo. First look at the commit history
git log -- filename
You should see a git commit for the svn commit you did. Hope you are in the habit of writing good comments when you svn commit.
git checkout commit-hash filename # restores the copy from svn
More tips
- If you know subversion pretty well check this out: http://git.or.cz/course/svn.html
- There are a few tech talks with helpful information about git:
There is several git GUIs - if you use Gnome giggle is a good choice
yum install giggle giggle &
Older patches might not apply cleanly against the latest sources. In such cases it's better to create a branch rooted in the revision against the patch was created, apply and commit the patch and then rebase it to master's HEAD. To find a git commit from SVN revision number:
git svn find-rev r10645 # make sure that 'r' is here
If you encounter problems when rebasing or merging 'git mergetool' command can be used to launch graphical 3-way merging tool. Make sure that you run it from the root of your git repository.
git rebase master # ... reports merge conflicts git mergetool # launches your favorite merge tool (meld in my case) # after you merge all conflicting changes git rebase --continue
'checkout' and 'status' are probably 2 most commonly used commands. To add svn-like aliases for them:
git config --global alias.co checkout git config --global alias.st status
And now you can use 'st' and 'co' instead:
git st # instead of git status git co master # instead of git checkout master
Enable colorized output for various commands:
git config --global color.branch auto git config --global color.diff auto git config --global color.interactive auto git config --global color.status auto
If you use bash, use git-completion.bash. It let's you press <TAB> to display a list of commands, arguments and parameters. For example git checkout <TAB> will show the list of branches.
Source it in your ~/.bashrc:
. /path-to/git-completion.bash
To have the current branch appear on your bash prompt:
export PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
Mirroring all branches of subversion repository
To create a mirror of entire sipXecs repository (not just a mainline but also all the branches)
git svn clone http://sipxecs.sipfoundry.org/rep/sipXecs -T main -b branches --prefix=svn/ ecs
It does require git to get all the revision from subversion. It might take several hours so do it overnight. Use https instead of http if you have commit access. To see the list of all remote branches (branches mirroring subversion repository)
git branch -r
If you want to develop a feature that should be checked in to specific subversion branch create a topic branch based on a specific remote branch (instead of creating branch based on master). For example to develop in 3.8 branch
git checkout -b my-feature 3.8
If you want to roll back to a particular point in history ( say some feature that is currently broken used to work a week ago and is blocking your progress ): Look at your git repository using giggle. You will see each commit has a global UUID. You can pick out the specific point in history when the world still looked rosy by doing:
git checkout -b proxy-still-worked UUID
To rebase current branch against subversion branch.
git svn rebase
To fetch all remote branches.
git svn fetch --all
