Re: Patch (apply) vs. Pull
- From
Linus Torvalds <torvalds@osdl.org>
- Date
- Jun 21, 2005, 22:09 UTC
- Message-ID
- <Pine.LNX.4.58.0506211452110.2353@ppc970.osdl.org>
- In-Reply-To
- <7vbr61j631.fsf@assigned-by-dhcp.cox.net>
On Mon, 20 Jun 2005, Junio C Hamano wrote:
Show 23 quoted lines
> > FYI, here is what I have been doing: > > (1) Start from Linus HEAD. > > (2) Repeat develop-and-commit cycle. > > (3) Run "git format-patch" (not in Linus tree) to generate > patches. > > (4) Send them out and wait to see which one sticks. > > (5) Pull from Linus. > > (6) Throw away my HEAD, making Linus HEAD my HEAD, while > preserving changes I have made since I forked from him. I > use "jit-rewind" for this. > > (7) Examine patches that Linus rejected, and apply ones that I > still consider good, making one commit per patch. I use > "jit-patch" and "jit-commit -m" for this. > > (8) Go back to step 2.
Btw, I'd like to help automate the 6-7 stage with a different kind of merge logic.
The current "real merge" is the global history merge, and that's the kind that I personally want to use, since that's what makes sense from a "project lead" standpoint and for the people around me in the kernel space that are project leaders of their own.
However, as you point out, it's not necessarily the best kind of merge for the "individual developer" standpoint. Most individual developers don't necessarily want to merge their work, rather they want to "bring it forward" to the current tip. And I think git could help with that too.
It would be somewhat akin to the current git-merge-script, but instead of merging it based on the common parent, it would instead try to re-base all the local commits from the common parent onwards on top of the new remote head. That often makes more sense from the standpoint of a individual developer who wants to update his work to the remote head.
Something like this (this assumes FETCH_HEAD is the remote head that we just fetched with "git fetch xxx" and that we want to re-base to):
- get the different HEAD info set up, and save the original head in ORIG_HEAD, the way "git resolve" does for real merges:
: ${GIT_DIR=.git}orig=$(git-rev-parse HEAD) new=$(git-rev-parse FETCH_HEAD) common=$(git-merge-base $orig $new)
echo $orig > $GIT_DIR/ORIG_HEAD
- fast-forward to the new HEAD. We'll want to re-base everything off that. If that fails, exit out - we've got dirty state
git-read-tree -m -u $orig $new && exit 1
- for each commit that we had in our old tree but not in the common part, try to re-base it:
> FAILED_TO_CHERRYPICK for i in $(git-rev-list $orig ^$common) do git-cherry-pick $i || (echo $i >> FAILED_TO_CHERRYPICK) done if [ -s FAILED_TO_CHERRYPICK ]; then echo Some commits could not be cherry-picked, check by hand: cat FAILED_TO_CHERRYPICK fi
and here the "git-cherry-pick" thing is just a script that basically takes an old commit ID, and tries to re-apply it as a patch (with author data and commit messages, of course) on top of the current head. It would basically be nothing more than a "git-diff-tree $1" followed by tryign to figure out whether it had already been applied or whether it can be applied now.
What do you think?
Linus