--keep-empty::
Keep the commits that do not change anything from its
parents in the result.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--allow-empty-message::
By default, rebasing commits with an empty message will fail.
This option overrides that behavior, allowing commits with empty
messages to be rebased.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--skip::
Restart the rebasing process by skipping the current patch.
conflict happens, the side reported as 'ours' is the so-far rebased
series, starting with <upstream>, and 'theirs' is the working branch. In
other words, the sides are swapped.
+ +
+ See also INCOMPATIBLE OPTIONS below.
-s <strategy>::
--strategy=<strategy>::
+
Because 'git rebase' replays each commit from the working branch
on top of the <upstream> branch using the given strategy, using
- the 'ours' strategy simply discards all patches from the <branch>,
+ the 'ours' strategy simply empties all patches from the <branch>,
which makes little sense.
+ +
+ See also INCOMPATIBLE OPTIONS below.
-X <strategy-option>::
--strategy-option=<strategy-option>::
This implies `--merge` and, if no strategy has been
specified, `-s recursive`. Note the reversal of 'ours' and
'theirs' as noted above for the `-m` option.
+ +
+ See also INCOMPATIBLE OPTIONS below.
-S[<keyid>]::
--gpg-sign[=<keyid>]::
and after each change. When fewer lines of surrounding
context exist they all must match. By default no context is
ever ignored.
+ +
+ See also INCOMPATIBLE OPTIONS below.
- -f::
+ --no-ff::
--force-rebase::
- Force a rebase even if the current branch is up to date and
- the command without `--force` would return without doing anything.
+ -f::
+ Individually replay all rebased commits instead of fast-forwarding
+ over the unchanged ones. This ensures that the entire history of
+ the rebased branch is composed of new commits.
+
- You may find this (or --no-ff with an interactive rebase) helpful after
- reverting a topic branch merge, as this option recreates the topic branch with
- fresh commits so it can be remerged successfully without needing to "revert
- the reversion" (see the
- link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
+ You may find this helpful after reverting a topic branch merge, as this option
+ recreates the topic branch with fresh commits so it can be remerged
+ successfully without needing to "revert the reversion" (see the
+ link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for
+ details).
--fork-point::
--no-fork-point::
--whitespace=<option>::
These flag are passed to the 'git apply' program
(see linkgit:git-apply[1]) that applies the patch.
- Incompatible with the --interactive option.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--committer-date-is-author-date::
--ignore-date::
These flags are passed to 'git am' to easily change the dates
of the rebased commits (see linkgit:git-am[1]).
- Incompatible with the --interactive option.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--signoff::
Add a Signed-off-by: trailer to all the rebased commits. Note
that if `--interactive` is given then only commits marked to be
- picked, edited or reworded will have the trailer added. Incompatible
- with the `--preserve-merges` option.
+ picked, edited or reworded will have the trailer added.
+ +
+ See also INCOMPATIBLE OPTIONS below.
-i::
--interactive::
The commit list format can be changed by setting the configuration option
rebase.instructionFormat. A customized instruction format will automatically
have the long commit hash prepended to the format.
+ +
+ See also INCOMPATIBLE OPTIONS below.
-r::
--rebase-merges[=(rebase-cousins|no-rebase-cousins)]::
`recursive` merge strategy; Different merge strategies can be used only via
explicit `exec git merge -s <strategy> [...]` commands.
+
- See also REBASING MERGES below.
+ See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
-p::
--preserve-merges::
This uses the `--interactive` machinery internally, but combining it
with the `--interactive` option explicitly is generally not a good
idea unless you know what you are doing (see BUGS below).
+ +
+ See also INCOMPATIBLE OPTIONS below.
-x <cmd>::
--exec <cmd>::
+
This uses the `--interactive` machinery internally, but it can be run
without an explicit `--interactive`.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--root::
Rebase all commits reachable from <branch>, instead of
When used together with both --onto and --preserve-merges,
'all' root commits will be rewritten to have <newbase> as parent
instead.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--autosquash::
--no-autosquash::
too. The recommended way to create fixup/squash commits is by using
the `--fixup`/`--squash` options of linkgit:git-commit[1].
+
- This option is only valid when the `--interactive` option is used.
- +
If the `--autosquash` option is enabled by default using the
configuration variable `rebase.autoSquash`, this option can be
used to override and disable this setting.
+ +
+ See also INCOMPATIBLE OPTIONS below.
--autostash::
--no-autostash::
with care: the final stash application after a successful
rebase might result in non-trivial conflicts.
- --no-ff::
- With --interactive, cherry-pick all rebased commits instead of
- fast-forwarding over the unchanged ones. This ensures that the
- entire history of the rebased branch is composed of new commits.
- +
- Without --interactive, this is a synonym for --force-rebase.
- +
- You may find this helpful after reverting a topic branch merge, as this option
- recreates the topic branch with fresh commits so it can be remerged
- successfully without needing to "revert the reversion" (see the
- link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
+ INCOMPATIBLE OPTIONS
+ --------------------
+
+ git-rebase has many flags that are incompatible with each other,
+ predominantly due to the fact that it has three different underlying
+ implementations:
+
+ * one based on linkgit:git-am[1] (the default)
+ * one based on git-merge-recursive (merge backend)
+ * one based on linkgit:git-cherry-pick[1] (interactive backend)
+
+ Flags only understood by the am backend:
+
+ * --committer-date-is-author-date
+ * --ignore-date
+ * --whitespace
+ * --ignore-whitespace
+ * -C
+
+ Flags understood by both merge and interactive backends:
+
+ * --merge
+ * --strategy
+ * --strategy-option
+ * --allow-empty-message
+
+ Flags only understood by the interactive backend:
+
+ * --[no-]autosquash
+ * --rebase-merges
+ * --preserve-merges
+ * --interactive
+ * --exec
+ * --keep-empty
+ * --autosquash
+ * --edit-todo
+ * --root when used in combination with --onto
+
+ Other incompatible flag pairs:
+
+ * --preserve-merges and --interactive
+ * --preserve-merges and --signoff
+ * --preserve-merges and --rebase-merges
+ * --rebase-merges and --strategy
+ * --rebase-merges and --strategy-option
+
+ BEHAVIORAL DIFFERENCES
+ -----------------------
+
+ * empty commits:
+
+ am-based rebase will drop any "empty" commits, whether the
+ commit started empty (had no changes relative to its parent to
+ start with) or ended empty (all changes were already applied
+ upstream in other commits).
+
+ merge-based rebase does the same.
+
+ interactive-based rebase will by default drop commits that
+ started empty and halt if it hits a commit that ended up empty.
+ The `--keep-empty` option exists for interactive rebases to allow
+ it to keep commits that started empty.
+
+ * directory rename detection:
+
+ merge-based and interactive-based rebases work fine with
+ directory rename detection. am-based rebases sometimes do not.
include::merge-strategies.txt[]
case" recovery too!
REBASING MERGES
------------------
+---------------
The interactive rebase command was originally designed to handle
individual patch series. As such, it makes sense to exclude merge
r,rebase-merges? try to rebase merges instead of skipping them
p,preserve-merges! try to recreate merges instead of ignoring them
s,strategy=! use the given merge strategy
+ X,strategy-option=! pass the argument through to the merge strategy
no-ff! cherry-pick all commits, even if unchanged
+ f,force-rebase! cherry-pick all commits, even if unchanged
m,merge! use merging strategies to rebase
i,interactive! let the user edit the list of commits to rebase
x,exec=! add exec lines after each commit of the editable list
k,keep-empty preserve empty commits during rebase
allow-empty-message allow rebasing commits with empty messages
- f,force-rebase! force rebase even if branch is up to date
- X,strategy-option=! pass the argument through to the merge strategy
stat! display a diffstat of what changed upstream
n,no-stat! do not show diffstat of what changed upstream
verify allow pre-rebase hook to run
rerere-autoupdate allow rerere to update index with resolved conflicts
root! rebase all reachable commits up to the root(s)
autosquash move commits that begin with squash!/fixup! under -i
+ signoff add a Signed-off-by: line to each commit
committer-date-is-author-date! passed to 'git am'
ignore-date! passed to 'git am'
- signoff passed to 'git am'
whitespace=! passed to 'git apply'
ignore-whitespace! passed to 'git apply'
C=! passed to 'git apply'
preserve_merges=
autosquash=
keep_empty=
- allow_empty_message=
+ allow_empty_message=--allow-empty-message
signoff=
test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
case "$(git config --bool commit.gpgsign)" in
autosquash=
fi
. git-rebase--$type
- git_rebase__$type${preserve_merges:+__preserve_merges}
+
+ if test -z "$preserve_merges"
+ then
+ git_rebase__$type
+ else
+ git_rebase__preserve_merges
+ fi
+
ret=$?
if test $ret -eq 0
then
state_dir="$apply_dir"
elif test -d "$merge_dir"
then
- if test -f "$merge_dir"/interactive
+ if test -d "$merge_dir"/rewritten
+ then
+ type=preserve-merges
+ interactive_rebase=explicit
+ preserve_merges=t
+ elif test -f "$merge_dir"/interactive
then
type=interactive
interactive_rebase=explicit
do_merge=t
;;
--strategy-option=*)
- strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}")"
+ strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}" | sed -e s/^.//)"
do_merge=t
test -z "$strategy" && strategy=recursive
;;
then
test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
# Only interactive rebase uses detailed reflog messages
- if test "$type" = interactive && test "$GIT_REFLOG_ACTION" = rebase
+ if test -n "$interactive_rebase" && test "$GIT_REFLOG_ACTION" = rebase
then
GIT_REFLOG_ACTION="rebase -i ($action)"
export GIT_REFLOG_ACTION
fi
fi
-if test "$action" = "edit-todo" && test "$type" != "interactive"
+if test "$action" = "edit-todo" && test -z "$interactive_rebase"
then
die "$(gettext "The --edit-todo action can only be used during interactive rebase.")"
fi
if test -n "$interactive_rebase"
then
- type=interactive
+ if test -z "$preserve_merges"
+ then
+ type=interactive
+ else
+ type=preserve-merges
+ fi
+
state_dir="$merge_dir"
elif test -n "$do_merge"
then
git_format_patch_opt="$git_format_patch_opt --progress"
fi
+ if test -n "$git_am_opt"; then
+ incompatible_opts=$(echo " $git_am_opt " | \
+ sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
+ if test -n "$interactive_rebase"
+ then
+ if test -n "$incompatible_opts"
+ then
+ die "$(gettext "error: cannot combine interactive options (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + --onto) with am options ($incompatible_opts)")"
+ fi
+ fi
+ if test -n "$do_merge"; then
+ if test -n "$incompatible_opts"
+ then
+ die "$(gettext "error: cannot combine merge options (--merge, --strategy, --strategy-option) with am options ($incompatible_opts)")"
+ fi
+ fi
+ fi
+
if test -n "$signoff"
then
test -n "$preserve_merges" &&
force_rebase=t
fi
+ if test -n "$preserve_merges"
+ then
+ # Note: incompatibility with --signoff handled in signoff block above
+ # Note: incompatibility with --interactive is just a strong warning;
+ # git-rebase.txt caveats with "unless you know what you are doing"
+ test -n "$rebase_merges" &&
+ die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
+ fi
+
+ if test -n "$rebase_merges"
+ then
+ test -n "$strategy_opts" &&
+ die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
+ test -n "$strategy" &&
+ die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
+ fi
+
if test -z "$rebase_root"
then
case "$#" in
# but this should be done only when upstream and onto are the same
# and if this is not an interactive rebase.
mb=$(git merge-base "$onto" "$orig_head")
-if test "$type" != interactive && test "$upstream" = "$onto" &&
+if test -z "$interactive_rebase" && test "$upstream" = "$onto" &&
test "$mb" = "$onto" && test -z "$restrict_revision" &&
# linear history?
! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
fi
-test "$type" = interactive && run_specific_rebase
+test -n "$interactive_rebase" && run_specific_rebase
# Detach HEAD and reset the tree
say "$(gettext "First, rewinding head to replay your work on top of it...")"
'
test_expect_success 'aborted --continue does not squash commits after "edit"' '
+ test_when_finished "git rebase --abort" &&
old=$(git rev-parse HEAD) &&
test_tick &&
set_fake_editor &&
FAKE_LINES="edit 1" git rebase -i HEAD^ &&
echo "edited again" > file7 &&
git add file7 &&
- test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue &&
- test $old = $(git rev-parse HEAD) &&
- git rebase --abort
+ echo all the things >>conflict &&
+ test_must_fail git rebase --continue &&
+ test $old = $(git rev-parse HEAD)
'
test_expect_success 'auto-amend only edited commits after "edit"' '
test -z "$(git show -s --format=%p HEAD^)"
'
+test_expect_success 'rebase -i --root when root has untracked file confilct' '
+ test_when_finished "reset_rebase" &&
+ git checkout -b failing-root-pick A &&
+ echo x >file2 &&
+ git rm file1 &&
+ git commit -m "remove file 1 add file 2" &&
+ echo z >file1 &&
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="1 2" git rebase -i --root &&
+ rm file1 &&
+ git rebase --continue &&
+ test "$(git log -1 --format=%B)" = "remove file 1 add file 2" &&
+ test "$(git rev-list --count HEAD)" = 2
+'
+
+test_expect_success 'rebase -i --root reword root when root has untracked file conflict' '
+ test_when_finished "reset_rebase" &&
+ echo z>file1 &&
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="reword 1 2" \
+ FAKE_COMMIT_MESSAGE="Modified A" git rebase -i --root &&
+ rm file1 &&
+ FAKE_COMMIT_MESSAGE="Reworded A" git rebase --continue &&
+ test "$(git log -1 --format=%B HEAD^)" = "Reworded A" &&
+ test "$(git rev-list --count HEAD)" = 2
+'
+
test_expect_success C_LOCALE_OUTPUT 'rebase --edit-todo does not work on non-interactive rebase' '
+ git checkout reword-root-branch &&
git reset --hard &&
git checkout conflict-branch &&
set_fake_editor &&