Skip to content

Commit f606c6e

Browse files
pks-tgitster
authored andcommitted
builtin/history: introduce "fixup" subcommand
The newly introduced git-history(1) command provides functionality to easily edit commit history while also rebasing dependent branches. The functionality exposed by this command is still somewhat limited though. One common use case when editing commit history that is not yet covered is fixing up a specific commit. Introduce a new subcommand that allows the user to do exactly that by performing a three-way merge into the target's commit tree, using HEAD's tree as the merge base. The flow is thus essentially: $ echo changes >file $ git add file $ git history fixup HEAD~ Like with the other commands, this will automatically rebase dependent branches, as well. Unlike the other commands though: - The command does not work in a bare repository as it interacts with the index. - The command may run into merge conflicts. If so, the command will simply abort. Especially the second item limits the usefulness of this command a bit. But there are plans to introduce first-class conflicts into Git, which will help use cases like this one. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3868254 commit f606c6e

4 files changed

Lines changed: 998 additions & 6 deletions

File tree

Documentation/git-history.adoc

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ git-history - EXPERIMENTAL: Rewrite history
88
SYNOPSIS
99
--------
1010
[synopsis]
11+
git history fixup <commit> [--dry-run] [--update-refs=(branches|head)] [--reedit-message] [--empty=(drop|keep|abort)]
1112
git history reword <commit> [--dry-run] [--update-refs=(branches|head)]
1213
git history split <commit> [--dry-run] [--update-refs=(branches|head)] [--] [<pathspec>...]
1314

@@ -22,8 +23,9 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
2223
This command is related to linkgit:git-rebase[1] in that both commands can be
2324
used to rewrite history. There are a couple of major differences though:
2425

25-
* linkgit:git-history[1] can work in a bare repository as it does not need to
26-
touch either the index or the worktree.
26+
* Most subcommands of linkgit:git-history[1] can work in a bare repository as
27+
they do not need to touch either the index or the worktree. The `fixup`
28+
subcommand is an exception to this, as it reads staged changes from the index.
2729
* linkgit:git-history[1] does not execute any linkgit:githooks[5] at the
2830
current point in time. This may change in the future.
2931
* linkgit:git-history[1] by default updates all branches that are descendants
@@ -48,11 +50,27 @@ conflicts. This limitation is by design as history rewrites are not intended to
4850
be stateful operations. The limitation can be lifted once (if) Git learns about
4951
first-class conflicts.
5052

53+
When using `fixup` with `--empty=drop`, dropping the root commit is not yet
54+
supported.
55+
5156
COMMANDS
5257
--------
5358

5459
The following commands are available to rewrite history in different ways:
5560

61+
`fixup <commit>`::
62+
Apply the currently staged changes to the specified commit. This
63+
is done by performing a three-way merge between the HEAD commit,
64+
the target commit and the tree generated from staged changes.
65+
This is using the same logic as linkgit:git-cherry-pick[1].
66+
+
67+
The commit message and authorship of the target commit are preserved by
68+
default, unless you specify `--reedit-message`.
69+
+
70+
If applying the staged changes would result in a conflict, the command
71+
aborts with an error. All branches that are descendants of the original
72+
commit are updated to point to the rewritten history.
73+
5674
`reword <commit>`::
5775
Rewrite the commit message of the specified commit. All the other
5876
details of this commit remain unchanged. This command will spawn an
@@ -87,6 +105,31 @@ OPTIONS
87105
objects will be written into the repository, so applying these printed
88106
ref updates is generally safe.
89107

108+
`--reedit-message`::
109+
Open an editor to modify the target commit's message.
110+
111+
`--empty=(drop|keep|abort)`::
112+
Control what happens when a commit becomes empty as a result of the
113+
fixup. This can happen in two situations:
114+
+
115+
--
116+
* The fixup target itself becomes empty because the staged changes exactly
117+
cancel out all changes introduced by that commit.
118+
119+
* A descendant commit becomes empty during replay because it introduced the
120+
same change that was just fixed up into an ancestor.
121+
--
122+
+
123+
With `drop` (the default), empty commits are removed from the rewritten
124+
history. Descendants of a dropped target commit are replayed directly onto
125+
the target's parent. Note that dropping the root commit is not supported;
126+
see LIMITATIONS.
127+
+
128+
With `keep`, empty commits are retained in the rewritten history as-is.
129+
+
130+
With `abort`, the command stops with an error if any commit would become
131+
empty.
132+
90133
`--update-refs=(branches|head)`::
91134
Control which references will be updated by the command, if any. With
92135
`branches`, all local branches that point to commits which are
@@ -96,6 +139,36 @@ OPTIONS
96139
EXAMPLES
97140
--------
98141

142+
Fixup a commit
143+
~~~~~~~~~~~~~~
144+
145+
----------
146+
$ git log --oneline --stat
147+
abc1234 (HEAD -> main) third
148+
third.txt | 1 +
149+
def5678 second
150+
second.txt | 1 +
151+
ghi9012 first
152+
first.txt | 1 +
153+
154+
$ echo "change" >>unrelated.txt
155+
$ git add unrelated.txt
156+
$ git history fixup ghi9012
157+
158+
$ git log --oneline --stat
159+
jkl3456 (HEAD -> main) third
160+
third.txt | 1 +
161+
mno7890 second
162+
second.txt | 1 +
163+
pqr1234 first
164+
first.txt | 1 +
165+
unrelated.txt | 1 +
166+
----------
167+
168+
The staged addition of `unrelated.txt` has been incorporated into the `first`
169+
commit. All descendant commits have been replayed on top of the rewritten
170+
history.
171+
99172
Split a commit
100173
~~~~~~~~~~~~~~
101174

0 commit comments

Comments
 (0)