| 1 | git-history(1) |
| 2 | ============== |
| 3 | |
| 4 | NAME |
| 5 | ---- |
| 6 | git-history - EXPERIMENTAL: Rewrite history |
| 7 | |
| 8 | SYNOPSIS |
| 9 | -------- |
| 10 | [synopsis] |
| 11 | git history drop <commit> [--dry-run] [--update-refs=(branches|head)] [--empty=(drop|keep|abort)] |
| 12 | git history fixup <commit> [--dry-run] [--update-refs=(branches|head)] [--reedit-message] [--empty=(drop|keep|abort)] |
| 13 | git history reword <commit> [--dry-run] [--update-refs=(branches|head)] |
| 14 | git history split <commit> [--dry-run] [--update-refs=(branches|head)] [--] [<pathspec>...] |
| 15 | git history squash [--dry-run] [--update-refs=(branches|head)] [--[no-]edit] <revision-range> |
| 16 | |
| 17 | DESCRIPTION |
| 18 | ----------- |
| 19 | |
| 20 | Rewrite history by rearranging or modifying specific commits in the |
| 21 | history. |
| 22 | |
| 23 | THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. |
| 24 | |
| 25 | This command is related to linkgit:git-rebase[1] in that both commands can be |
| 26 | used to rewrite history. There are a couple of major differences though: |
| 27 | |
| 28 | * Most subcommands of linkgit:git-history[1] can work in a bare repository as |
| 29 | they do not need to touch either the index or the worktree. The `fixup` |
| 30 | subcommand is an exception to this, as it reads staged changes from the index. |
| 31 | * linkgit:git-history[1] does not execute any linkgit:githooks[5] at the |
| 32 | current point in time. This may change in the future. |
| 33 | * linkgit:git-history[1] by default updates all branches that are descendants |
| 34 | of the original commit to point to the rewritten commit. |
| 35 | |
| 36 | Overall, linkgit:git-history[1] aims to provide a more opinionated way to modify |
| 37 | your commit history that is simpler to use compared to linkgit:git-rebase[1] in |
| 38 | general. |
| 39 | |
| 40 | Use linkgit:git-rebase[1] if you want to reapply a range of commits onto a |
| 41 | different base, or interactive rebases if you want to edit a range of commits |
| 42 | at once. |
| 43 | |
| 44 | LIMITATIONS |
| 45 | ----------- |
| 46 | |
| 47 | This command does not (yet) replay merge commits onto the rewritten |
| 48 | history: if a commit that would be replayed is a merge, the operation is |
| 49 | rejected, and you should use linkgit:git-rebase[1] with the |
| 50 | `--rebase-merges` flag instead. The `squash` subcommand can still fold a |
| 51 | merge that lies inside the range, as long as the range has a single base. |
| 52 | |
| 53 | Furthermore, the command does not support operations that can result in merge |
| 54 | conflicts. This limitation is by design as history rewrites are not intended to |
| 55 | be stateful operations. The limitation can be lifted once (if) Git learns about |
| 56 | first-class conflicts. |
| 57 | |
| 58 | When using `fixup` with `--empty=drop`, dropping the root commit is not yet |
| 59 | supported. Likewise, `drop` cannot remove the root commit or a merge commit. |
| 60 | |
| 61 | COMMANDS |
| 62 | -------- |
| 63 | |
| 64 | The following commands are available to rewrite history in different ways: |
| 65 | |
| 66 | `drop <commit>`:: |
| 67 | Remove the specified commit from the history. All descendants of the |
| 68 | commit are replayed directly onto its parent. |
| 69 | + |
| 70 | The root commit cannot be dropped as that may lead to edge cases where refs |
| 71 | end up with no commits anymore. Merge commits cannot be dropped either; see |
| 72 | LIMITATIONS. |
| 73 | + |
| 74 | If `HEAD` points at a commit that is to be rewritten, the index and working |
| 75 | tree are updated to match the new `HEAD`. The command aborts before any |
| 76 | references are updated in case local modifications would be overwritten. |
| 77 | + |
| 78 | If replaying any descendant would result in a conflict, the command aborts |
| 79 | with an error. |
| 80 | |
| 81 | `fixup <commit>`:: |
| 82 | Apply the currently staged changes to the specified commit. This is |
| 83 | similar in nature to `git commit --fixup=<commit>` followed by `git |
| 84 | rebase --autosquash <commit>~`. Changes are applied to the target |
| 85 | commit by performing a three-way merge between the HEAD commit, the |
| 86 | target commit and the tree generated from staged changes. |
| 87 | + |
| 88 | The commit message and authorship of the target commit are preserved by |
| 89 | default, unless you specify `--reedit-message`. |
| 90 | + |
| 91 | If applying the staged changes would result in a conflict, the command |
| 92 | aborts with an error. All branches that are descendants of the original |
| 93 | commit are updated to point to the rewritten history. |
| 94 | |
| 95 | `reword <commit>`:: |
| 96 | Rewrite the commit message of the specified commit. All the other |
| 97 | details of this commit remain unchanged. This command will spawn an |
| 98 | editor with the current message of that commit. |
| 99 | |
| 100 | `split <commit> [--] [<pathspec>...]`:: |
| 101 | Interactively split up <commit> into two commits by choosing |
| 102 | hunks introduced by it that will be moved into the new split-out |
| 103 | commit. These hunks will then be written into a new commit that |
| 104 | becomes the parent of the previous commit. The original commit |
| 105 | stays intact, except that its parent will be the newly split-out |
| 106 | commit. |
| 107 | + |
| 108 | The commit messages of the split-up commits will be asked for by launching |
| 109 | the configured editor. Authorship of the commit will be the same as for the |
| 110 | original commit. |
| 111 | + |
| 112 | If passed, _<pathspec>_ can be used to limit which changes shall be split out |
| 113 | of the original commit. Files not matching any of the pathspecs will remain |
| 114 | part of the original commit. For more details, see the 'pathspec' entry in |
| 115 | linkgit:gitglossary[7]. |
| 116 | + |
| 117 | It is invalid to select either all or no hunks, as that would lead to |
| 118 | one of the commits becoming empty. |
| 119 | |
| 120 | `squash <revision-range>`:: |
| 121 | Fold all commits in _<revision-range>_ into the oldest commit of that |
| 122 | range. The resulting commit keeps the oldest commit's authorship and |
| 123 | takes the tree of the range's newest commit, so the whole range |
| 124 | collapses into a single commit. Commits above the range are replayed |
| 125 | on top of the result. |
| 126 | + |
| 127 | The range is given in the usual `<base>..<tip>` form, where _<base>_ is |
| 128 | the commit just below the oldest commit to squash. For example, `git |
| 129 | history squash HEAD~3..HEAD` folds the three most recent commits into |
| 130 | one, and `git history squash HEAD~5..HEAD~2` squashes an interior range |
| 131 | while leaving the two newest commits in place. Several revisions may be |
| 132 | given, for example `HEAD~3..HEAD ^topic` to additionally exclude what is |
| 133 | already on `topic`. Rev-list options may also be given, but any that would |
| 134 | change how the range is walked are overridden with a warning. |
| 135 | + |
| 136 | An editor opens pre-filled with the messages of all the folded commits so |
| 137 | you can combine them. With `--no-edit`, the oldest commit's message is |
| 138 | preserved instead, except that an `amend!` commit targeting it replaces its |
| 139 | message. A merge commit inside the range is folded like any other, but the |
| 140 | range must have a single base and a single tip. A range that reaches more |
| 141 | than one entry point (for example a side branch that forked before the range |
| 142 | and was later merged into it), or that selects two unmerged tips, is rejected. |
| 143 | + |
| 144 | A `fixup!`, `squash!`, or `amend!` commit is refused unless the commit it |
| 145 | targets is also in the range, so the fold does not silently absorb a |
| 146 | marker meant for a commit outside it. As an exception, a range made up entirely |
| 147 | of markers for one target is combined into a single commit. With `--no-edit`, |
| 148 | the last `amend!` message is used if there is one. |
| 149 | + |
| 150 | The template mirrors `git rebase -i --autosquash`: each `fixup!`, `squash!`, |
| 151 | or `amend!` is grouped under the commit it targets rather than shown in |
| 152 | commit order. A `fixup!` message is dropped (commented out in full), a |
| 153 | `squash!` keeps its body with only the marker subject commented, and an |
| 154 | `amend!` replaces its target's message, unless a `squash!` folded into that |
| 155 | target first, in which case it keeps its body like a `squash!`. |
| 156 | + |
| 157 | A local branch that points at a commit inside the range cannot be rewritten |
| 158 | as a descendant of the result, so with the default `--update-refs=branches` |
| 159 | the command refuses. Rerun with `--update-refs=head` to rewrite only the |
| 160 | current branch and leave such branches pointing at the old commits. Tags and |
| 161 | remote-tracking refs are always left unchanged. |
| 162 | |
| 163 | OPTIONS |
| 164 | ------- |
| 165 | |
| 166 | `--dry-run`:: |
| 167 | Do not update any references, but instead print any ref updates in a |
| 168 | format that can be consumed by linkgit:git-update-ref[1]. Necessary new |
| 169 | objects will be written into the repository, so applying these printed |
| 170 | ref updates is generally safe. |
| 171 | |
| 172 | `--edit`:: |
| 173 | `--no-edit`:: |
| 174 | For `squash`, open an editor to combine the messages of the folded commits. |
| 175 | This is the default; use `--no-edit` to keep the selected message |
| 176 | without opening an editor. |
| 177 | |
| 178 | `--reedit-message`:: |
| 179 | Open an editor to modify the target commit's message. |
| 180 | |
| 181 | `--empty=(drop|keep|abort)`:: |
| 182 | Control what happens when a commit becomes empty as a result of the |
| 183 | fixup. This can happen in two situations: |
| 184 | + |
| 185 | -- |
| 186 | * The fixup target itself becomes empty because the staged changes exactly |
| 187 | cancel out all changes introduced by that commit. |
| 188 | |
| 189 | * A descendant commit becomes empty during replay because it introduced the |
| 190 | same change that was just fixed up into an ancestor. |
| 191 | -- |
| 192 | + |
| 193 | With `drop` (the default), empty commits are removed from the rewritten |
| 194 | history. Descendants of a dropped target commit are replayed directly onto |
| 195 | the target's parent. Note that dropping the root commit is not supported; |
| 196 | see LIMITATIONS. |
| 197 | + |
| 198 | With `keep`, empty commits are retained in the rewritten history as-is. |
| 199 | + |
| 200 | With `abort`, the command stops with an error if any commit would become |
| 201 | empty. |
| 202 | |
| 203 | `--update-refs=(branches|head)`:: |
| 204 | Control which references will be updated by the command, if any. With |
| 205 | `branches`, all local branches that point to commits which are |
| 206 | descendants of the original commit will be rewritten. With `head`, only |
| 207 | the current `HEAD` reference will be rewritten. Defaults to `branches`. |
| 208 | |
| 209 | EXAMPLES |
| 210 | -------- |
| 211 | |
| 212 | Fixup a commit |
| 213 | ~~~~~~~~~~~~~~ |
| 214 | |
| 215 | ---------- |
| 216 | $ git log --oneline --stat |
| 217 | abc1234 (HEAD -> main) third |
| 218 | third.txt | 1 + |
| 219 | def5678 second |
| 220 | second.txt | 1 + |
| 221 | ghi9012 first |
| 222 | first.txt | 1 + |
| 223 | |
| 224 | $ echo "change" >>unrelated.txt |
| 225 | $ git add unrelated.txt |
| 226 | $ git history fixup ghi9012 |
| 227 | |
| 228 | $ git log --oneline --stat |
| 229 | jkl3456 (HEAD -> main) third |
| 230 | third.txt | 1 + |
| 231 | mno7890 second |
| 232 | second.txt | 1 + |
| 233 | pqr1234 first |
| 234 | first.txt | 1 + |
| 235 | unrelated.txt | 1 + |
| 236 | ---------- |
| 237 | |
| 238 | The staged addition of `unrelated.txt` has been incorporated into the `first` |
| 239 | commit. All descendant commits have been replayed on top of the rewritten |
| 240 | history. |
| 241 | |
| 242 | Drop a commit |
| 243 | ~~~~~~~~~~~~~ |
| 244 | |
| 245 | ---------- |
| 246 | $ git log --oneline |
| 247 | abc1234 (HEAD -> main) third |
| 248 | def5678 second |
| 249 | ghi9012 first |
| 250 | |
| 251 | $ git history drop 'main^{/second}' |
| 252 | |
| 253 | $ git log --oneline |
| 254 | jkl3456 (HEAD -> main) third |
| 255 | ghi9012 first |
| 256 | ---------- |
| 257 | |
| 258 | The `second` commit has been removed from the history, and `third` has been |
| 259 | replayed directly on top of `first`. All branches that pointed at the dropped |
| 260 | commit have been moved to its parent. |
| 261 | |
| 262 | Split a commit |
| 263 | ~~~~~~~~~~~~~~ |
| 264 | |
| 265 | ---------- |
| 266 | $ git log --stat --oneline |
| 267 | 3f81232 (HEAD -> main) original |
| 268 | bar | 1 + |
| 269 | foo | 1 + |
| 270 | 2 files changed, 2 insertions(+) |
| 271 | |
| 272 | $ git history split HEAD |
| 273 | diff --git a/bar b/bar |
| 274 | new file mode 100644 |
| 275 | index 0000000..5716ca5 |
| 276 | --- /dev/null |
| 277 | +++ b/bar |
| 278 | @@ -0,0 +1 @@ |
| 279 | +bar |
| 280 | (1/1) Stage addition [y,n,q,a,d,p,?]? y |
| 281 | |
| 282 | diff --git a/foo b/foo |
| 283 | new file mode 100644 |
| 284 | index 0000000..257cc56 |
| 285 | --- /dev/null |
| 286 | +++ b/foo |
| 287 | @@ -0,0 +1 @@ |
| 288 | +foo |
| 289 | (1/1) Stage addition [y,n,q,a,d,p,?]? n |
| 290 | |
| 291 | $ git log --stat --oneline |
| 292 | 7cebe64 (HEAD -> main) original |
| 293 | foo | 1 + |
| 294 | 1 file changed, 1 insertion(+) |
| 295 | d1582f3 split-out commit |
| 296 | bar | 1 + |
| 297 | 1 file changed, 1 insertion(+) |
| 298 | ---------- |
| 299 | |
| 300 | GIT |
| 301 | --- |
| 302 | Part of the linkgit:git[1] suite |