summaryrefslogtreecommitdiff
path: root/Documentation/howto/rebase-and-edit.txt
blob: 6cc1c7921f0bab8ec2c2b02e47594f57246b141b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
	rm .git/refs/heads/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