Difference between revisions of "Git"

From GnuCash
Jump to: navigation, search
(remove some old sections)
(First part of complete rewrite for Github repository.)
Line 1: Line 1:
Git is an extremely cool version control system, but a bit geeky to get used to it. For gnucash, it can be used to hold a local copy of the full [[svn]] repository, which means extremely fast version browsing. Also, it is possible to prepare your commits in your local repository first, and sending them to the gnucash [[svn]] server sometime later in a batch. Also extremely cool.
+
= Git and Gnucash =
  
Note, it might be easier to follow trunk via [[bazaar]].
+
== What is Git? ==
  
Webpage: http://git-scm.com/
+
[http://git-scm.com/ Git] is a distributed version control system originally developed by Linus Torvalds for managing Linux source code without requiring a central server. It is also the primary VCS used by the [http://www.gnome.org Gnome] and [http://www.freedesktop.org Free Desktop] projects. You can get the latest version for your system and read a rich variety of online documentation at [http://git-scm.com/ Git's Home].
  
Note: You should install git >= 1.5.0 because svn handling has improved considerably with these versions. Really. Don't bother with any 1.4 version; it plainly sucks in comparison to the latest versions.
+
== What has that to do with Gnucash? ==
  
== Single Branch Setup ==
+
Some of Gnucash's primary developers are experimenting with using Git to take advantage of its branching and merging facilities, which are much richer than those provided by Subversion. We have an experimental repository at [https://github.com/Gnucash/gnucash Github] which is updated from the canonical subversion repository every 4 hours.
If you want to checkout only one single branch, here's what you would do:
 
  
Here's how you as a developer get your local git repository if you only want ''trunk'' (git-1.5.2):
+
== Using the Github Repository ==
git svn clone -r20000:HEAD svn+ssh://USERNAME@svn.gnucash.org/repo/gnucash/trunk
 
  
That's it. The revision subset r20000:HEAD will download approx. 30-40 MB of data. If you download larger revision spans, the download amount might go up into the hundreds of MBs.
+
=== Non-Committers ===
  
Here's how you run the equivalent of "svn update":
+
Just clone the repository as usual:
git svn rebase
 
  
That's it.
+
  git clone git://github.com/Gnucash/gnucash.git
  
Once you committed your changes to your local git repository, here's how you commit the local changes upstream into gnucash's SVN repository:
+
When you have patches, use
git svn dcommit
 
  
== Catchup from public clone ==
+
  git diff > patchfile
  
clone a public git repo ( http://github.com/timabell/gnucash-svn/ ) that follows the svn server:
+
in the root directory of your local repository to prepare them; then add the patchfile as an attachment to the appropriate bug report.
  
git clone git://github.com/timabell/gnucash-svn.git gnucash.git
+
If you have a Github account, you can fork Gnucash from within Github and clone your forked repository. This allows you to publish your fork and allows Gnucash developers to pull your changes. Please '''don't''' use the Github "pull request" mechanism; we can't work directly in the Github repository because it would break synchronization with subversion.
cd gnucash.git
 
 
 
attach your copy to the gnucash svn server:
 
 
 
git svn init -s http://svn.gnucash.org/repo/gnucash/
 
 
 
FIXME: there's got to be a quick way of telling git that it already has enough information about the svn server. I'm sure I did it once before. The below seems to re-fetch everything. --[[User:Tim abell|Tim abell]] 19:59, 4 March 2009 (EST) see http://utsl.gen.nz/talks/git-svn/intro.html#howto-track-rebuildmeta looks like i'm missing metadata on the github copy
 
 
 
update: looks like i'm expecting too much from the git packaged with ubuntu intrepid (1.5.6.3)
 
"You probably also want git 1.6.1rc for incremental rebuild support" http://kerneltrap.org/mailarchive/git/2008/12/7/4338304 --[[User:Tim abell|Tim abell]] 15:51, 5 March 2009 (EST)
 
 
 
fetch changes from the svn server. this will (annoyingly) reread all the commits, you wouldn't expect this to take as long as a public clone, but I haven't had ay luck so far.
 
 
 
git svn fetch
 
 
 
example output:
 
 
 
$ time git svn fetch
 
...
 
M po/fi.po
 
M po/zh_CN.po
 
r18050 = a93e209b78c7ca59b1bb8f81fee0a92efefad92a (trunk)
 
M src/report/utility-reports/view-column.scm
 
r18051 = 284772dea8fbc8bdc64c3e7c3840bc026a2093f8 (trunk)
 
 
real 519m30.791s
 
user 44m43.660s
 
sys 78m44.703s
 
 
 
 
 
 
 
update your copy again (beware that rebase breaks commit references, make sure you are ok with this)
 
 
 
git svn rebase
 
 
 
push to a public git server so that others can benefit from your more up to date copy
 
 
 
hack on the code
 
 
 
push your own genius new gnucash features to your own public git server for all to see and share :-)
 
 
 
contact the mailing list to get your changes in the mainline.
 
 
 
=== technical details ===
 
svn section of .git/config from original git svn clone:
 
[svn-remote "svn"]
 
url = http://svn.gnucash.org/repo
 
fetch = gnucash/trunk:refs/remotes/trunk
 
branches = gnucash/branches/*:refs/remotes/*
 
tags = gnucash/tags/*:refs/remotes/tags/*
 
 
 
=== references ===
 
* http://kerneltrap.org/index.php?q=mailarchive/git/2008/5/8/1760964/thread
 
* http://marc.info/?l=git&m=122868184208156&w=2
 
 
 
== Advanced setup: graft points ==
 
There is a git clone on GitHub at http://github.com/timabell/gnucash/ (cloned 31 jan 2009).  It is already out of date as GitHub doesn't support tracking remote svn repositories.  However, you can use it to efficiently "deepen" the history for a "shallow" checkout of trunk:
 
 
 
1) Checkout ''trunk'' as described above.  Use the subset r17856:HEAD; we'll get the rest from GitHub.
 
git svn clone -r17856:HEAD svn+ssh://USERNAME@svn.gnucash.org/repo/gnucash/trunk
 
 
 
2) Fetch the rest of the history from GitHub.
 
git-fetch git://github.com/timabell/gnucash.git
 
 
 
3) Find the latest commit in this history, here is what you should see:
 
 
 
$ git ls-remote git://github.com/timabell/gnucash.git HEAD
 
5cabf7a61dee17c188a67d8cdbc4451d1b8ae7de        HEAD
 
$ git branch history 5cabf7a61dee17c188a67d8cdbc4451d1b8ae7de
 
$ git log history^..history
 
commit 5cabf7a61dee17c188a67d8cdbc4451d1b8ae7de
 
Author: cstim <cstim@57a11ea4-9604-0410-9ed3-97b8803252fd>
 
Date:  Sat Jan 31 10:24:34 2009 +0000
 
 
    Add shell script to easily back-port commits in git-svn from trunk to other branches.
 
 
 
4) Find the corresponding commit from svn:
 
 
 
$ git svn log --show-commit -r17856
 
------------------------------------------------------------------------
 
r17856 | 048f138 | cstim | 2009-01-31 10:24:34 +0000 (Sat, 31 Jan 2009) | 2 lines
 
 
Add shell script to easily back-port commits in git-svn from trunk to other branches.
 
 
------------------------------------------------------------------------
 
$ git-rev-parse 048f138
 
048f1384a4bba73e438615630218568a4446c00f
 
 
 
5) Graft the two histories together:
 
$ PARENT=$(git-rev-parse history^)
 
$ echo 048f1384a4bba73e438615630218568a4446c00f $PARENT >> .git/info/grafts
 
 
 
== Multi-Branch Setup ==
 
If you want to checkout all of the currently active branches and have the ability to merge and cherry-pick back and forth between all branches locally, you can do it by checking out the branches in your local repo, or you can make clones of your local repos. This latter method has a slight advantage over the first method:  When changing between the branches, git would change your working directory, hence a more or less extensive build process is going on, dependent on the amount of files that are different between the branches. Here the second method in detail:
 
 
 
git svn clone -s -r16500:HEAD svn+ssh://USERNAME@svn.gnucash.org/repo/gnucash all
 
cd all
 
git branch --track my-trunk remotes/trunk
 
git branch --track my-2.2 remotes/2.2
 
cd ..
 
 
 
This will need <tt>git svn --fetch-all rebase</tt> so that all SVN branches are updated in parallel.
 
 
 
Creating a working copy for ''trunk'':
 
cd all
 
git checkout my-trunk
 
cd ..
 
git clone -s all trunk
 
 
 
And another working copy for ''branches/2.2'':
 
cd all
 
git checkout my-2.2
 
cd ..
 
git clone -s all 2.2
 
 
 
Building one branch:
 
cd 2.2
 
./autogen.sh
 
mkdir build
 
cd build
 
../configure --some-options-foo-bar --prefix=/opt/experimental .....
 
 
 
(... FIXME: more text later ...)
 
 
 
Here's how you as a developer get your local git repository if you want ''trunk and all branches'' (git-1.5.2), pay attention to the ''-s'' switch:
 
git svn clone -s -r16500:HEAD svn+ssh://USERNAME@svn.gnucash.org/repo/gnucash
 
git reset --hard remotes/trunk
 
The latter command is necessary if your local ''master'' should represent the ''trunk'' of SVN, which is probably what you want. You need ''reset --hard'' here instead of ''rebase'' because the revision subset ''r16500:HEAD'' probably doesn't contain the original branch point between some of the other svn branches and trunk. If the branch point is included in your cloned revision subset, ''git rebase remotes/trunk'' would work as well and is safer (i.e. won't throw away any local changes without asking).
 
 
 
Starting at r16500 is a good opportunity because the 2.2 branch is branched at approx. r16560; if you need the gda-dev: that one was created at r15090.
 
 
 
== Full import process ==
 
As used to create http://github.com/timabell/gnucash-svn
 
 
 
This is mostly just for reference or in case anyone else wants to do the same as me. --[[User:Tim abell|Tim abell]] 16:21, 4 March 2009 (EST)
 
 
 
The idea is to be able to track the bleeding edge in git, with one central shared copy, without requiring the existing devs to move away from svn.
 
 
 
=== full clone ===
 
git svn clone -s http://svn.gnucash.org/repo/gnucash/ gnucash-svn.git
 
cd gnucash-svn.git
 
 
 
=== push to github===
 
create github repo (on their website) and then:
 
 
 
git remote add origin git@github.com:timabell/gnucash-svn.git
 
git push origin master
 
 
 
to push up the svn metadata:
 
 
 
git config --add remote.origin.fetch +refs/remotes/*:refs/remotes/*
 
git push origin
 
 
 
=== copying branches ===
 
 
 
for remote in `git branch -r`; do git branch $remote remotes/$remote ; done
 
 
 
Thanks to http://stackoverflow.com/questions/379081/track-all-remote-git-branches-as-local-branches
 
 
 
git branch -D origin/master
 
 
 
(was duplicated)
 
 
 
git branch -D trunk
 
 
 
(master will suffice, don't need a second branch to track the bleeding edge)
 
 
 
git push --all origin
 
 
 
=== fixing tags ===
 
using modified version of http://beardedmagnum.com/2009/02/15/converting-git-svn-tag-branches-to-real-tags/
 
 
 
this creates a local tag for each branch named tag/*
 
 
 
because svn includes a commit as part of tagging, whether or not you change anything, I need to figure out whether any files are affected by the tag commit.
 
 
 
if nothing was changed, i can safely tag the parent commit.
 
 
 
testing if commit changed anything:
 
 
 
git show --pretty="format:" --name-only tags/1.4.3 | wc -l
 
 
 
outputs 53, so this tag commit includes changes
 
 
 
git show --pretty="format:" --name-only tags/1.5.0 | wc -l
 
 
 
outputs 0 so this commit can be ignored and the parent commit tagged instead.
 
 
 
testing the output:
 
 
 
if [ `git show --pretty="format:" --name-only tags/1.5.0 | wc -l` -gt "0" ]; then echo "files changed in tag commit (boo)"; else echo "no changes in tag commit"; fi
 
 
 
putting it all together:
 
 
 
git for-each-ref refs/heads/tags | cut -d / -f 4- | \
 
while read ref
 
do
 
  if [ `git show --pretty="format:" --name-only tags/$ref | wc -l` -gt "0" ]; then
 
  #commit contains changes
 
  git tag $ref tags/$ref
 
  else
 
  #no changes, tag parent commit
 
  git tag $ref tags/$ref^
 
  fi
 
done
 
 
 
delete all the old local tag branches:
 
git for-each-ref refs/heads/tags | cut -d / -f 3-| xargs git branch -D
 
 
 
push all the new tags to the server:
 
git tag | xargs git push origin
 
 
 
remove remote tag branches (if you pushed them like i did)
 
git for-each-ref refs/remotes/origin/tags | cut -d / -f 4- | while read ref; do git push origin :refs/heads/$ref; done
 
 
 
or to delete them all at once
 
  git for-each-ref refs/remotes/origin/tags | cut -d / -f 4- | sed "s/^/\:refs\/heads\//" | xargs git push origin
 
 
 
=== passing through updates ===
 
 
 
Note, I've only had changes on master to handle so far, so that's all I'm documenting.
 
 
 
git svn rebase
 
git push origin master
 
 
 
sorted.
 
 
 
== Further Research ==
 
 
 
http://github.com/nirvdrum/svn2git a ruby tool for performing imports.this one. jcoglan (author)
 

Revision as of 19:56, 8 March 2011

Git and Gnucash

What is Git?

Git is a distributed version control system originally developed by Linus Torvalds for managing Linux source code without requiring a central server. It is also the primary VCS used by the Gnome and Free Desktop projects. You can get the latest version for your system and read a rich variety of online documentation at Git's Home.

What has that to do with Gnucash?

Some of Gnucash's primary developers are experimenting with using Git to take advantage of its branching and merging facilities, which are much richer than those provided by Subversion. We have an experimental repository at Github which is updated from the canonical subversion repository every 4 hours.

Using the Github Repository

Non-Committers

Just clone the repository as usual:

 git clone git://github.com/Gnucash/gnucash.git

When you have patches, use

 git diff > patchfile

in the root directory of your local repository to prepare them; then add the patchfile as an attachment to the appropriate bug report.

If you have a Github account, you can fork Gnucash from within Github and clone your forked repository. This allows you to publish your fork and allows Gnucash developers to pull your changes. Please don't use the Github "pull request" mechanism; we can't work directly in the Github repository because it would break synchronization with subversion.