| Date:	Sat, 13 Aug 2005 22:16:02 -0700 (PDT) | 
 | From:	Linus Torvalds <torvalds@osdl.org> | 
 | To:	Steve French <smfrench@austin.rr.com> | 
 | cc:	git@vger.kernel.org | 
 | Subject: Re: sending changesets from the middle of a git tree | 
 | Abstract: In this article, Linus demonstrates how a broken commit | 
 |  in a sequence of commits can be removed by rewinding the head and | 
 |  reapplying selected changes. | 
 |  | 
 | On Sat, 13 Aug 2005, Linus Torvalds wrote: | 
 |  | 
 | > That's correct. Same things apply: you can move a patch over, and create a  | 
 | > new one with a modified comment, but basically the _old_ commit will be  | 
 | > immutable. | 
 |  | 
 | Let me clarify. | 
 |  | 
 | You can entirely _drop_ old branches, so commits may be immutable, but | 
 | nothing forces you to keep them. Of course, when you drop a commit, you'll  | 
 | always end up dropping all the commits that depended on it, and if you  | 
 | actually got somebody else to pull that commit you can't drop it from  | 
 | _their_ repository, but undoing things is not impossible. | 
 |  | 
 | For example, let's say that you've made a mess of things: you've committed | 
 | three commits "old->a->b->c", and you notice that "a" was broken, but you | 
 | want to save "b" and "c". What you can do is | 
 |  | 
 | 	# Create a branch "broken" that is the current code | 
 | 	# for reference | 
 | 	git branch broken | 
 |  | 
 | 	# Reset the main branch to three parents back: this  | 
 | 	# effectively undoes the three top commits | 
 | 	git reset HEAD^^^ | 
 | 	git checkout -f | 
 |  | 
 | 	# Check the result visually to make sure you know what's | 
 | 	# going on | 
 | 	gitk --all | 
 |  | 
 | 	# Re-apply the two top ones from "broken" | 
 | 	# | 
 | 	# First "parent of broken" (aka b): | 
 | 	git-diff-tree -p broken^ | git-apply --index | 
 | 	git commit --reedit=broken^ | 
 |  | 
 | 	# Then "top of broken" (aka c): | 
 | 	git-diff-tree -p broken | git-apply --index | 
 | 	git commit --reedit=broken | 
 |  | 
 | and you've now re-applied (and possibly edited the comments) the two | 
 | commits b/c, and commit "a" is basically gone (it still exists in the | 
 | "broken" branch, of course). | 
 |  | 
 | Finally, check out the end result again: | 
 |  | 
 | 	# Look at the new commit history | 
 | 	gitk --all | 
 |  | 
 | to see that everything looks sensible. | 
 |  | 
 | And then, you can just remove the broken branch if you decide you really  | 
 | don't want it: | 
 |  | 
 | 	# remove 'broken' branch | 
 | 	git branch -d broken | 
 |  | 
 | 	# Prune old objects if you're really really sure | 
 | 	git prune | 
 |  | 
 | And yeah, I'm sure there are other ways of doing this. And as usual, the  | 
 | above is totally untested, and I just wrote it down in this email, so if  | 
 | I've done something wrong, you'll have to figure it out on your own ;) | 
 |  | 
 | 			Linus | 
 | - | 
 | To unsubscribe from this list: send the line "unsubscribe git" in | 
 | the body of a message to majordomo@vger.kernel.org | 
 | More majordomo info at  http://vger.kernel.org/majordomo-info.html | 
 |  | 
 |  |