Front page | perl.perl5.porters |
Postings from November 2008
Re: git workflow (was Re: git?)
From: Chris Prather
November 16, 2008 17:50
Re: git workflow (was Re: git?)
Message ID: firstname.lastname@example.org
> Right. This makes sense. So to me, right now, the useful assistance I'd like
> would be to have documented how have a git workflow as close as is sane to the
> current perforce commit-to-blead workflow.
So based on questions asked on IRC, I whipped up the following and
rand it past Sam Vilain (SamV below, I would be perigrin).
P5P Pumpkin Workflow
21:47 <@Nicholas> I don't think it's hugely written down yet
21:47 <@Nicholas> it's roughly
21:47 <@Nicholas> step 1: anyone applies patches to blead
21:48 <@Nicholas> step 2: $someone_in_particular in charge of this
merges it to maint-5.10
21:48 <@Nicholas> step 3: again, someone in particular merges from
maint-5.10 to maint-5.8
21:48 <@Nicholas> plus
21:49 <@Nicholas> anything not relevant to blead is done in maint-5.10
21:49 <@Nicholas> and anything not relevant to the other two is done
21:49 <@Nicholas> plsu a step 0
21:49 <@Nicholas> step 0: if someone sends us a patch related to a
dual life module, we pass it on to the CPAN
maintainer, and wait for them to make a release with
21:49 <@Nicholas> "step 1" included "new stuff on CPAN"
First the assumption is that you've cloned the perl5 git repo so that
it being tracked by git as the remote called 'origin'. That is that to
get your local copy of the git repo you ran
`git clone git://perl5.git.perl.org/perl.git`
Which will leave a copy of the perl5 source tree in the directory
'perl'. We'll also assume that you're currently in the 'perl'
In simple steps in Git:
1) Fetch any new patches to blead.
To fetch the changes from the upstream repository we `fetch` them
`git fetch origin`
Then to see what changes happened in blead we can look in the `git log`
`git log origin/blead`
Once we find the commit ID for the change we want to import into
maint-5.10 we can move onto the next step. Let's assume we're using
commit id f8467450c3ffefbf2b0c08f47f48b7caee554b26.
2) Merge into maint-5.10
We checkout a copy of the maint-5.10 tree into a local branch for
working on our changes
`git checkout --track -b integrate_foo_patch origin/maint-5.10`
(SamV - or `git checkout --track origin/maint-5.10` on newer gits; and I'm
trying hard to get them to make this the behaviour of plain `git
We now can cherry pick the specific patch from the blead tree that we
want to apply. We use the -n switch so that cherry-pick won't
automatically commit this patch and give us a chance to perform any
cleanup we need for 5.10 that wasn't necessary for blead.
`git cherry-pick --no-commit f8467450c3ffefbf2b0c08f47f48b7caee554b26`
Now we're left with a working directory that contains the maint-5.10
branch + the patch we just applied. We can clean up the patch and make
sure that everything is working before committing. Once we're
satisfied that this patch is properly integrated we can commit our
changes to our `integrate_foo_patch` branch.
(SamV - overcome your fear of commitment. Er, committing. If it
didn't work, you can change it and then run `git commit --amend
filename`, or use `git-gui --amend` to do it interactively.
Additionally that will mean that you can combine steps 1 and 2 of
these instructions, by just having `gitk origin/blead` open, and
right-click the commits you want and hit "cherry pick this commit")
(perigrin - I've explicitly left the --no-commit because while *I* know about
things like `git commit --ammend` and `git rebase -i` I don't want to make
assumptions on the reader's level of knowledge of comfort and I feel it's
better to be non-destructive to begin with. )
First we check to see what git things we have done
Now for every file we've modified and added we need to stage it for commit by
adding it to the index. For every file we've changed or added we do
`git add [path to file]`
and finally once we are sure we have everything added or modified we
can commit to our local repository
(SamV - allow me to cargo cult against `git commit -a` - don't do
that. Explicitly stage for commit all the files you want in the
change with 'git add' or individual hunks using 'git add -p', and then
'git commit' when you're done. 'git gui' provides a nice interface
for this. Use `git diff --cached` to see the staged changes as a
This will make sure that any files we have modified will get picked
up in the commit and will dump us into `$EDTIOR` asking for a commit
message. Finally we push this back to the remote repository.
`git push origin HEAD`
This will take the changes we have performed locally and push them
back to the remote repository with the commit log for others to clone.
(SamV - another piece of UI nastiness lurks here that I'm currently
campaigning to change the behaviour of. Unadorned, unconfigured `git
push` has some quite strange behaviour; it doesn't just push the
branch you're on, it pushes *all* branches with matching names to the
remote end. Until my proposals to make this behaviour more sane hit
the version of git you're using, use the explicit notation: `git push
origin branchname` - or add a `push = HEAD` line to the remote section
in `.git/config` (`git config remote.origin.push HEAD`)
(perigrin - noted and updated)
3) Merge into maint-5.8
We simply perform the same steps we did for maint-5.10 for 5.8.
But... wait... how does git track this?
It doesn't. Basically git is designed to work with projects that merge from
stable to unstable, rather than those that go the other way.
When a patch is cherry picked, the "patch id" will be the same, so long as it
wasn't resolved using diff3. This can be seen with `git patch-id`; it's
roughly a sha1 sum of the diff for a patch. You can use this to see which
commits introduce *exactly* the same changes to the same exact files using:
`git rev-list --left-right --cherry-pick branchA...branchB`
I suggest if this model is going to be continued and the git-style stable
model not used, then someone implements this:
* `git-cherry-pick` should have an option to record the OLD patch ID in the
commit message if it changed (or the patch did not merge cleanly). This
would be a bit like `git cherry-pick -x`
This change has been suggested before, even approved by Linus, it
just needs to be written.
* write a script to create an index of patch IDs to commit IDs for fast lookup
* ideally, hack support into `git-rev-parse`, or (to really hack it) just
`gitk` and `gitweb` for using this index so that the patch ID links can
be made hot for easier use