Browse Source
I would eventually like to move this to become a part of the tutorial, but anyway, this was an excellent post that describes how topic branches can be used to keep track of local changes.maint

1 changed files with 153 additions and 0 deletions
@ -0,0 +1,153 @@ |
|||||||
|
Date: Mon, 15 Aug 2005 12:17:41 -0700 |
||||||
|
From: tony.luck@intel.com |
||||||
|
Subject: Some tutorial text (was git/cogito workshop/bof at linuxconf au?) |
||||||
|
|
||||||
|
Here's something that I've been putting together on how I'm using |
||||||
|
GIT as a Linux subsystem maintainer. |
||||||
|
|
||||||
|
I suspect that I'm a bit slap-happy with the "git checkout" commands in |
||||||
|
the examples below, and perhaps missing some of the _true-git_ ways of |
||||||
|
doing things. |
||||||
|
|
||||||
|
-Tony |
||||||
|
|
||||||
|
Linux subsystem maintenance using GIT |
||||||
|
------------------------------------- |
||||||
|
|
||||||
|
My requirements here are to be able to create two public trees: |
||||||
|
|
||||||
|
1) A "test" tree into which patches are initially placed so that they |
||||||
|
can get some exposure when integrated with other ongoing development. |
||||||
|
This tree is available to Andrew for pulling into -mm whenever he wants. |
||||||
|
|
||||||
|
2) A "release" tree into which tested patches are moved for final |
||||||
|
sanity checking, and as a vehicle to send them upstream to Linus |
||||||
|
(by sending him a "please pull" request.) |
||||||
|
|
||||||
|
Note that the period of time that each patch spends in the "test" tree |
||||||
|
is dependent on the complexity of the change. Since GIT does not support |
||||||
|
cherry picking, it is not practical to simply apply all patches to the |
||||||
|
test tree and then pull to the release tree as that would leave trivial |
||||||
|
patches blocked in the test tree waiting for complex changes to accumulate |
||||||
|
enough test time to graduate. |
||||||
|
|
||||||
|
Back in the BitKeeper days I achieved this my creating small forests of |
||||||
|
temporary trees, one tree for each logical grouping of patches, and then |
||||||
|
pulling changes from these trees first to the test tree, and then to the |
||||||
|
release tree. At first I replicated this in GIT, but then I realised |
||||||
|
that I could so this far more efficiently using branches inside a single |
||||||
|
GIT repository. |
||||||
|
|
||||||
|
So here is the step-by-step guide how this all works for me. |
||||||
|
|
||||||
|
First create your work tree by cloning Linus's public tree: |
||||||
|
|
||||||
|
$ git clone rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work |
||||||
|
|
||||||
|
Change directory into the cloned tree you just created |
||||||
|
|
||||||
|
$ cd work |
||||||
|
|
||||||
|
Make a GIT branch named "linus", and rename the "origin" branch as linus too: |
||||||
|
|
||||||
|
$ git checkout -b linus |
||||||
|
$ mv .git/branches/origin .git/branches/linus |
||||||
|
|
||||||
|
The "linus" branch will be used to track the upstream kernel. To update it, |
||||||
|
you simply run: |
||||||
|
|
||||||
|
$ git checkout linus && git pull linus |
||||||
|
|
||||||
|
you can do this frequently (as long as you don't have any uncommited work |
||||||
|
in your tree). |
||||||
|
|
||||||
|
If you need to keep track of other public trees, you can add branches for |
||||||
|
them too: |
||||||
|
|
||||||
|
$ git checkout -b another linus |
||||||
|
$ echo URL-for-another-public-tree > .git/branches/another |
||||||
|
|
||||||
|
Now create the branches in which you are going to work, these start |
||||||
|
out at the current tip of the linus branch. |
||||||
|
|
||||||
|
$ git checkout -b test linus |
||||||
|
$ git checkout -b release linus |
||||||
|
|
||||||
|
These can be easily kept up to date by merging from the "linus" branch: |
||||||
|
|
||||||
|
$ git checkout test && git resolve test linus "Auto-update from upstream" |
||||||
|
$ git checkout release && git resolve release linus "Auto-update from upstream" |
||||||
|
|
||||||
|
Set up so that you can push upstream to your public tree: |
||||||
|
|
||||||
|
$ echo master.kernel.org:/ftp/pub/scm/linux/kernel/git/aegl/linux-2.6.git > .git/branches/origin |
||||||
|
|
||||||
|
and then push each of the test and release branches using: |
||||||
|
|
||||||
|
$ git push origin test |
||||||
|
and |
||||||
|
$ git push origin release |
||||||
|
|
||||||
|
Now to apply some patches from the community. Think of a short |
||||||
|
snappy name for a branch to hold this patch (or related group of |
||||||
|
patches), and create a new branch from the current tip of the |
||||||
|
linus branch: |
||||||
|
|
||||||
|
$ git checkout -b speed-up-spinlocks linus |
||||||
|
|
||||||
|
Now you apply the patch(es), run some tests, and commit the change(s). If |
||||||
|
the patch is a multi-part series, then you should apply each as a separate |
||||||
|
commit to this branch. |
||||||
|
|
||||||
|
$ ... patch ... test ... commit [ ... patch ... test ... commit ]* |
||||||
|
|
||||||
|
When you are happy with the state of this change, you can pull it into the |
||||||
|
"test" branch in preparation to make it public: |
||||||
|
|
||||||
|
$ git checkout test && git resolve test speed-up-spinlocks "Pull speed-up-spinlock changes" |
||||||
|
|
||||||
|
It is unlikely that you would have any conflicts here ... but you might if you |
||||||
|
spent a while on this step and had also pulled new versions from upstream. |
||||||
|
|
||||||
|
Some time later when enough time has passed and testing done, you can pull the |
||||||
|
same branch into the "release" tree ready to go upstream. This is where you |
||||||
|
see the value of keeping each patch (or patch series) in its own branch. It |
||||||
|
means that the patches can be moved into the "release" tree in any order. |
||||||
|
|
||||||
|
$ git checkout release && git resolve release speed-up-spinlocks "Pull speed-up-spinlock changes" |
||||||
|
|
||||||
|
After a while, you will have a number of branches, and despite the |
||||||
|
well chosen names you picked for each of them, you may forget what |
||||||
|
they are for, or what status they are in. To get a reminder of what |
||||||
|
changes are in a specific branch, use: |
||||||
|
|
||||||
|
$ git-whatchanged branchname ^linus | git-shortlog |
||||||
|
|
||||||
|
To see whether it has already been merged into the test or release branches |
||||||
|
use: |
||||||
|
|
||||||
|
$ git-rev-list branchname ^test |
||||||
|
or |
||||||
|
$ git-rev-list branchname ^release |
||||||
|
|
||||||
|
[If this branch has not yet been merged you will see a set of SHA1 values |
||||||
|
for the commits, if it has been merged, then there will be no output] |
||||||
|
|
||||||
|
Once a patch completes the great cycle (moving from test to release, then |
||||||
|
pulled by Linus, and finally coming back into your local "linus" branch) |
||||||
|
the branch for this change is no longer needed. You detect this when the |
||||||
|
output from: |
||||||
|
|
||||||
|
$ git-rev-list branchname ^linus |
||||||
|
|
||||||
|
is empty. At this point the branch can be deleted: |
||||||
|
|
||||||
|
$ rm .git/refs/heads/branchname |
||||||
|
|
||||||
|
To create diffstat and shortlog summaries of changes to include in a "please |
||||||
|
pull" request to Linus you can use: |
||||||
|
|
||||||
|
$ git-whatchanged -p release ^linus | diffstat -p1 |
||||||
|
and |
||||||
|
$ git-whatchanged release ^linus | git-shortlog |
||||||
|
|
Loading…
Reference in new issue