Movatterモバイル変換


[0]ホーム

URL:


Git
English ▾Topics ▾ Latest version ▾git-rebase last updated in 2.50.0

NAME

git-rebase - Reapply commits on top of another base tip

SYNOPSIS

git rebase [-i | --interactive] [<options>] [--exec <cmd>][--onto <newbase> | --keep-base] [<upstream> [<branch>]]git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]--root [<branch>]git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)

DESCRIPTION

If<branch> is specified,gitrebase will perform an automaticgitswitch<branch> before doing anything else. Otherwiseit remains on the current branch.

If<upstream> is not specified, the upstream configured inbranch.<name>.remote andbranch.<name>.merge options will be used (seegit-config[1] for details) and the--fork-point option isassumed. If you are currently not on any branch or if the currentbranch does not have a configured upstream, the rebase will abort.

All changes made by commits in the current branch but that are notin<upstream> are saved to a temporary area. This is the same setof commits that would be shown bygitlog<upstream>..HEAD; or bygitlogfork_point'..HEAD, if--fork-point is active (see thedescription on--fork-point below); or bygitlogHEAD, if the--root option is specified.

The current branch is reset to<upstream> or<newbase> if the--onto option was supplied. This has the exact same effect asgitreset--hard<upstream> (or<newbase>).ORIG_HEAD is setto point at the tip of the branch before the reset.

Note
ORIG_HEAD is not guaranteed to still point to the previous branch tipat the end of the rebase if other commands that write that pseudo-ref(e.g.gitreset) are used during the rebase. The previous branch tip,however, is accessible using the reflog of the current branch(i.e.@{1}, seegitrevisions[7]).

The commits that were previously saved into the temporary area arethen reapplied to the current branch, one by one, in order. Note thatany commits inHEAD which introduce the same textual changes as a commitinHEAD..<upstream> are omitted (i.e., a patch already accepted upstreamwith a different commit message or timestamp will be skipped).

It is possible that a merge failure will prevent this process from beingcompletely automatic. You will have to resolve any such merge failureand rungitrebase--continue. Another option is to bypass the committhat caused the merge failure withgitrebase--skip. To check out theoriginal<branch> and remove the.git/rebase-apply working files, usethe commandgitrebase--abort instead.

Assume the following history exists and the current branch is "topic":

          A---B---C topic         /    D---E---F---G master

From this point, the result of either of the following commands:

git rebase mastergit rebase master topic

would be:

                  A'--B'--C' topic                 /    D---E---F---G master

NOTE: The latter form is just a short-hand ofgitcheckouttopicfollowed bygitrebasemaster. When rebase exitstopic willremain the checked-out branch.

If the upstream branch already contains a change you have made (e.g.,because you mailed a patch which was applied upstream), then that commitwill be skipped and warnings will be issued (if themerge backend isused). For example, runninggitrebasemaster on the followinghistory (in whichA' andA introduce the same set of changes, buthave different committer information):

          A---B---C topic         /    D---E---A'---F master

will result in:

                   B'---C' topic                  /    D---E---A'---F master

Here is how you would transplant a topic branch based on onebranch to another, to pretend that you forked the topic branchfrom the latter branch, usingrebase--onto.

First let’s assume yourtopic is based on branchnext.For example, a feature developed intopic depends on somefunctionality which is found innext.

    o---o---o---o---o  master         \          o---o---o---o---o  next                           \                            o---o---o  topic

We want to maketopic forked from branchmaster; for example,because the functionality on whichtopic depends was merged into themore stablemaster branch. We want our tree to look like this:

    o---o---o---o---o  master        |            \        |             o'--o'--o'  topic         \          o---o---o---o---o  next

We can get this using the following command:

git rebase --onto master next topic

Another example of --onto option is to rebase part of abranch. If we have the following situation:

                            H---I---J topicB                           /                  E---F---G  topicA                 /    A---B---C---D  master

then the command

git rebase --onto master topicA topicB

would result in:

                 H'--I'--J'  topicB                /                | E---F---G  topicA                |/    A---B---C---D  master

This is useful when topicB does not depend on topicA.

A range of commits could also be removed with rebase. If we havethe following situation:

    E---F---G---H---I---J  topicA

then the command

git rebase --onto topicA~5 topicA~3 topicA

would result in the removal of commits F and G:

    E---H'---I'---J'  topicA

This is useful if F and G were flawed in some way, or should not bepart of topicA. Note that the argument to--onto and the<upstream>parameter can be any valid commit-ish.

In case of conflict,gitrebase will stop at the first problematic commitand leave conflict markers in the tree. You can usegitdiff to locatethe markers (<<<<<<) and make edits to resolve the conflict. For eachfile you edit, you need to tell Git that the conflict has been resolved,typically this would be done with

git add <filename>

After resolving the conflict manually and updating the index with thedesired resolution, you can continue the rebasing process with

git rebase --continue

Alternatively, you can undo thegit rebase with

git rebase --abort

MODE OPTIONS

The options in this section cannot be used with any other option,including not with each other:

--continue

Restart the rebasing process after having resolved a merge conflict.

--skip

Restart the rebasing process by skipping the current patch.

--abort

Abort the rebase operation and reset HEAD to the originalbranch. If<branch> was provided when the rebase operation wasstarted, thenHEAD will be reset to<branch>. OtherwiseHEADwill be reset to where it was when the rebase operation wasstarted.

--quit

Abort the rebase operation butHEAD is not reset back to theoriginal branch. The index and working tree are also leftunchanged as a result. If a temporary stash entry was createdusing--autostash, it will be saved to the stash list.

--edit-todo

Edit the todo list during an interactive rebase.

--show-current-patch

Show the current patch in an interactive rebase or when rebaseis stopped because of conflicts. This is the equivalent ofgitshowREBASE_HEAD.

OPTIONS

--onto <newbase>

Starting point at which to create the new commits. If the--onto option is not specified, the starting point is<upstream>. May be any valid commit, and not just anexisting branch name.

As a special case, you may use "A...B" as a shortcut for themerge base of A and B if there is exactly one merge base. You canleave out at most one of A and B, in which case it defaults to HEAD.

--keep-base

Set the starting point at which to create the new commits to themerge base of<upstream> and<branch>. Runninggitrebase--keep-base<upstream><branch> is equivalent torunninggitrebase--reapply-cherry-picks--no-fork-point--onto<upstream>...<branch><upstream><branch>.

This option is useful in the case where one is developing a feature ontop of an upstream branch. While the feature is being worked on, theupstream branch may advance and it may not be the best idea to keeprebasing on top of the upstream but to keep the base commit as-is. Asthe base commit is unchanged this option implies--reapply-cherry-picksto avoid losing commits.

Although both this option and--fork-point find the merge base between<upstream> and<branch>, this option uses the merge base as thestartingpoint on which new commits will be created, whereas--fork-point usesthe merge base to determine theset of commits which will be rebased.

See also INCOMPATIBLE OPTIONS below.

<upstream>

Upstream branch to compare against. May be any valid commit,not just an existing branch name. Defaults to the configuredupstream for the current branch.

<branch>

Working branch; defaults toHEAD.

--apply

Use applying strategies to rebase (callinggit-aminternally). This option may become a no-op in the futureonce the merge backend handles everything the apply one does.

See also INCOMPATIBLE OPTIONS below.

--empty=(drop|keep|stop)

How to handle commits that are not empty to start and are notclean cherry-picks of any upstream commit, but which becomeempty after rebasing (because they contain a subset of alreadyupstream changes):

drop

The commit will be dropped. This is the default behavior.

keep

The commit will be kept. This option is implied when--exec isspecified unless-i/--interactive is also specified.

stop
ask

The rebase will halt when the commit is applied, allowing you tochoose whether to drop it, edit files more, or just commit the emptychanges. This option is implied when-i/--interactive isspecified.ask is a deprecated synonym ofstop.

Note that commits which start empty are kept (unless--no-keep-emptyis specified), and commits which are clean cherry-picks (as determinedbygitlog--cherry-mark ...) are detected and dropped as apreliminary step (unless--reapply-cherry-picks or--keep-base ispassed).

See also INCOMPATIBLE OPTIONS below.

--no-keep-empty
--keep-empty

Do not keep commits that start empty before the rebase(i.e. that do not change anything from its parent) in theresult. The default is to keep commits which start empty,since creating such commits requires passing the--allow-emptyoverride flag togitcommit, signifying that a user is veryintentionally creating such a commit and thus wants to keepit.

Usage of this flag will probably be rare, since you can get rid ofcommits that start empty by just firing up an interactive rebase andremoving the lines corresponding to the commits you don’t want. Thisflag exists as a convenient shortcut, such as for cases where externaltools generate many empty commits and you want them all removed.

For commits which do not start empty but become empty after rebasing,see the--empty flag.

See also INCOMPATIBLE OPTIONS below.

--reapply-cherry-picks
--no-reapply-cherry-picks

Reapply all clean cherry-picks of any upstream commit insteadof preemptively dropping them. (If these commits then becomeempty after rebasing, because they contain a subset of alreadyupstream changes, the behavior towards them is controlled bythe--empty flag.)

In the absence of--keep-base (or if--no-reapply-cherry-picks isgiven), these commits will be automatically dropped. Because thisnecessitates reading all upstream commits, this can be expensive inrepositories with a large number of upstream commits that need to beread. When using themerge backend, warnings will be issued for eachdropped commit (unless--quiet is given). Advice will also be issuedunlessadvice.skippedCherryPicks is set to false (seegit-config[1]).

--reapply-cherry-picks allows rebase to forgo reading all upstreamcommits, potentially improving performance.

See also INCOMPATIBLE OPTIONS below.

--allow-empty-message

No-op. Rebasing commits with an empty message used to failand this option would override that behavior, allowing commitswith empty messages to be rebased. Now commits with an emptymessage do not cause rebasing to halt.

See also INCOMPATIBLE OPTIONS below.

-m
--merge

Using merging strategies to rebase (default).

Note that a rebase merge works by replaying each commit from the workingbranch on top of the<upstream> branch. Because of this, when a mergeconflict happens, the side reported asours is the so-far rebasedseries, starting with<upstream>, andtheirs is the working branch.In other words, the sides are swapped.

See also INCOMPATIBLE OPTIONS below.

-s <strategy>
--strategy=<strategy>

Use the given merge strategy, instead of the defaultort.This implies--merge.

Becausegitrebase replays each commit from the working branchon top of the<upstream> branch using the given strategy, usingtheours strategy simply empties all patches from the<branch>,which makes little sense.

See also INCOMPATIBLE OPTIONS below.

-X <strategy-option>
--strategy-option=<strategy-option>

Pass the <strategy-option> through to the merge strategy.This implies--merge and, if no strategy has beenspecified,-sort. Note the reversal ofours andtheirs as noted above for the-m option.

See also INCOMPATIBLE OPTIONS below.

--rerere-autoupdate
--no-rerere-autoupdate

After the rerere mechanism reuses a recorded resolution onthe current conflict to update the files in the workingtree, allow it to also update the index with the result ofresolution.--no-rerere-autoupdate is a good way todouble-check whatrerere did and catch potentialmismerges, before committing the result to the index with aseparategitadd.

-S[<keyid>]
--gpg-sign[=<keyid>]
--no-gpg-sign

GPG-sign commits. Thekeyid argument is optional anddefaults to the committer identity; if specified, it must bestuck to the option without a space.--no-gpg-sign is useful tocountermand bothcommit.gpgSign configuration variable, andearlier--gpg-sign.

-q
--quiet

Be quiet. Implies--no-stat.

-v
--verbose

Be verbose. Implies--stat.

--stat

Show a diffstat of what changed upstream since the last rebase. Thediffstat is also controlled by the configuration option rebase.stat.

-n
--no-stat

Do not show a diffstat as part of the rebase process.

--no-verify

This option bypasses the pre-rebase hook. See alsogithooks[5].

--verify

Allows the pre-rebase hook to run, which is the default. This option canbe used to override--no-verify. See alsogithooks[5].

-C<n>

Ensure at least<n> lines of surrounding context match beforeand after each change. When fewer lines of surroundingcontext exist they all must match. By default no context isever ignored. Implies--apply.

See also INCOMPATIBLE OPTIONS below.

--no-ff
--force-rebase
-f

Individually replay all rebased commits instead of fast-forwardingover the unchanged ones. This ensures that the entire history ofthe rebased branch is composed of new commits.

You may find this helpful after reverting a topic branch merge, as this optionrecreates the topic branch with fresh commits so it can be remergedsuccessfully without needing to "revert the reversion" (see therevert-a-faulty-merge How-To fordetails).

--fork-point
--no-fork-point

Use reflog to find a better common ancestor between<upstream>and<branch> when calculating which commits have beenintroduced by<branch>.

When--fork-point is active,fork_point will be used instead of<upstream> to calculate the set of commits to rebase, wherefork_point is the result ofgitmerge-base--fork-point<upstream><branch> command (seegit-merge-base[1]). Iffork_pointends up being empty, the<upstream> will be used as a fallback.

If<upstream> or--keep-base is given on the command line, thenthe default is--no-fork-point, otherwise the default is--fork-point. See alsorebase.forkpoint ingit-config[1].

If your branch was based on<upstream> but<upstream> was rewound andyour branch contains commits which were dropped, this option can be usedwith--keep-base in order to drop those commits from your branch.

See also INCOMPATIBLE OPTIONS below.

--ignore-whitespace

Ignore whitespace differences when trying to reconciledifferences. Currently, each backend implements an approximation ofthis behavior:

apply backend

When applying a patch, ignore changes in whitespace in contextlines. Unfortunately, this means that if the "old" lines beingreplaced by the patch differ only in whitespace from the existingfile, you will get a merge conflict instead of a successful patchapplication.

merge backend

Treat lines with only whitespace changes as unchanged when merging.Unfortunately, this means that any patch hunks that were intendedto modify whitespace and nothing else will be dropped, even if theother side had no changes that conflicted.

--whitespace=<option>

This flag is passed to thegitapply program(seegit-apply[1]) that applies the patch.Implies--apply.

See also INCOMPATIBLE OPTIONS below.

--committer-date-is-author-date

Instead of using the current time as the committer date, usethe author date of the commit being rebased as the committerdate. This option implies--force-rebase.

--ignore-date
--reset-author-date

Instead of using the author date of the original commit, usethe current time as theauthor date of the rebased commit. Thisoption implies--force-rebase.

See also INCOMPATIBLE OPTIONS below.

--signoff

Add aSigned-off-by trailer to all the rebased commits. Notethat if--interactive is given then only commits marked to bepicked, edited or reworded will have the trailer added.

See also INCOMPATIBLE OPTIONS below.

-i
--interactive

Make a list of the commits which are about to be rebased. Let theuser edit that list before rebasing. This mode can also be used tosplit commits (see SPLITTING COMMITS below).

The commit list format can be changed by setting the configuration optionrebase.instructionFormat. A customized instruction format will automaticallyhave the commit hash prepended to the format.

See also INCOMPATIBLE OPTIONS below.

-r
--rebase-merges[=(rebase-cousins|no-rebase-cousins)]
--no-rebase-merges

By default, a rebase will simply drop merge commits from the todolist, and put the rebased commits into a single, linear branch.With--rebase-merges, the rebase will instead try to preservethe branching structure within the commits that are to be rebased,by recreating the merge commits. Any resolved merge conflicts ormanual amendments in these merge commits will have to beresolved/re-applied manually.--no-rebase-merges can be used tocountermand both therebase.rebaseMerges config option and a previous--rebase-merges.

When rebasing merges, there are two modes:rebase-cousins andno-rebase-cousins. If the mode is not specified, it defaults tono-rebase-cousins. Inno-rebase-cousins mode, commits which do not have<upstream> as direct ancestor will keep their original branch point, i.e.commits that would be excluded bygit-log[1]'s--ancestry-pathoption will keep their original ancestry by default. Inrebase-cousins mode,such commits are instead rebased onto<upstream> (or<onto>, ifspecified).

It is currently only possible to recreate the merge commits using theort merge strategy; different merge strategies can be used only viaexplicitexecgitmerge-s<strategy> [...] commands.

See also REBASING MERGES and INCOMPATIBLE OPTIONS below.

-x <cmd>
--exec <cmd>

Append "exec <cmd>" after each line creating a commit in thefinal history.<cmd> will be interpreted as one or more shellcommands. Any command that fails will interrupt the rebase,with exit code 1.

You may execute several commands by either using one instance of--execwith several commands:

git rebase -i --exec "cmd1 && cmd2 && ..."

or by giving more than one--exec:

git rebase -i --exec "cmd1" --exec "cmd2" --exec ...

If--autosquash is used,exec lines will not be appended forthe intermediate commits, and will only appear at the end of eachsquash/fixup series.

This uses the--interactive machinery internally, but it can be runwithout an explicit--interactive.

See also INCOMPATIBLE OPTIONS below.

--root

Rebase all commits reachable from<branch>, instead oflimiting them with an<upstream>. This allows you to rebasethe root commit(s) on a branch.

See also INCOMPATIBLE OPTIONS below.

--autosquash
--no-autosquash

Automatically squash commits with specially formatted messages intoprevious commits being rebased. If a commit message starts with"squash! ", "fixup! " or "amend! ", the remainder of the titleis taken as a commit specifier, which matches a previous commit if itmatches the title or the hash of that commit. If no commitmatches fully, matches of the specifier with the start of committitles are considered.

In the rebase todo list, the actions of squash, fixup and amend commits arechanged frompick tosquash,fixup orfixup-C, respectively, and theyare moved right after the commit they modify. The--interactive option canbe used to review and edit the todo list before proceeding.

The recommended way to create commits with squash markers is by using the--squash,--fixup,--fixup=amend: or--fixup=reword: options ofgit-commit[1], which take the target commit as an argument andautomatically fill in the title of the new commit from that.

Setting configuration variablerebase.autoSquash to true enablesauto-squashing by default for interactive rebase. The--no-autosquashoption can be used to override that setting.

See also INCOMPATIBLE OPTIONS below.

--autostash
--no-autostash

Automatically create a temporary stash entry before the operationbegins, and apply it after the operation ends. This meansthat you can run rebase on a dirty worktree. However, usewith care: the final stash application after a successfulrebase might result in non-trivial conflicts.

--reschedule-failed-exec
--no-reschedule-failed-exec

Automatically rescheduleexec commands that failed. This only makessense in interactive mode (or when an--exec option was provided).

This option applies once a rebase is started. It is preserved for the wholerebase based on, in order, the command line option provided to the initialgitrebase, therebase.rescheduleFailedExec configuration (seegit-config[1] or "CONFIGURATION" below), or it defaults to false.

Recording this option for the whole rebase is a convenience feature. Otherwisean explicit--no-reschedule-failed-exec at the start would be overridden bythe presence of arebase.rescheduleFailedExec=true configuration whengitrebase--continue is invoked. Currently, you cannot pass--[no-]reschedule-failed-exec togitrebase--continue.

--update-refs
--no-update-refs

Automatically force-update any branches that point to commits thatare being rebased. Any branches that are checked out in a worktreeare not updated in this way.

If the configuration variablerebase.updateRefs is set, then this optioncan be used to override and disable this setting.

See also INCOMPATIBLE OPTIONS below.

INCOMPATIBLE OPTIONS

The following options:

  • --apply

  • --whitespace

  • -C

are incompatible with the following options:

  • --merge

  • --strategy

  • --strategy-option

  • --autosquash

  • --rebase-merges

  • --interactive

  • --exec

  • --no-keep-empty

  • --empty=

  • --[no-]reapply-cherry-picks when used without --keep-base

  • --update-refs

  • --root when used without --onto

In addition, the following pairs of options are incompatible:

  • --keep-base and --onto

  • --keep-base and --root

  • --fork-point and --root

BEHAVIORAL DIFFERENCES

gitrebase has two primary backends:apply andmerge. (Theapplybackend used to be known as theam backend, but the name led toconfusion as it looks like a verb instead of a noun. Also, themergebackend used to be known as the interactive backend, but it is nowused for non-interactive cases as well. Both were renamed based onlower-level functionality that underpinned each.) There are somesubtle differences in how these two backends behave:

Empty commits

Theapply backend unfortunately drops intentionally empty commits, i.e.commits that started empty, though these are rare in practice. Italso drops commits that become empty and has no option for controllingthis behavior.

Themerge backend keeps intentionally empty commits by default (thoughwith-i they are marked as empty in the todo list editor, or they canbe dropped automatically with--no-keep-empty).

Similar to the apply backend, by default the merge backend dropscommits that become empty unless-i/--interactive is specified (inwhich case it stops and asks the user what to do). The merge backendalso has an--empty=(drop|keep|stop) option for changing the behaviorof handling commits that become empty.

Directory rename detection

Due to the lack of accurate tree information (arising fromconstructing fake ancestors with the limited information available inpatches), directory rename detection is disabled in theapply backend.Disabled directory rename detection means that if one side of historyrenames a directory and the other adds new files to the old directory,then the new files will be left behind in the old directory withoutany warning at the time of rebasing that you may want to move thesefiles into the new directory.

Directory rename detection works with themerge backend to provide youwarnings in such cases.

Context

Theapply backend works by creating a sequence of patches (by callingformat-patch internally), and then applying the patches in sequence(callingam internally). Patches are composed of multiple hunks,each with line numbers, a context region, and the actual changes. Theline numbers have to be taken with some offset, since the other sidewill likely have inserted or deleted lines earlier in the file. Thecontext region is meant to help find how to adjust the line numbers inorder to apply the changes to the right lines. However, if multipleareas of the code have the same surrounding lines of context, thewrong one can be picked. There are real-world cases where this hascaused commits to be reapplied incorrectly with no conflicts reported.Settingdiff.context to a larger value may prevent such types ofproblems, but increases the chance of spurious conflicts (since itwill require more lines of matching context to apply).

Themerge backend works with a full copy of each relevant file,insulating it from these types of problems.

Labelling of conflicts markers

When there are content conflicts, the merge machinery tries toannotate each side’s conflict markers with the commits where thecontent came from. Since theapply backend drops the originalinformation about the rebased commits and their parents (and insteadgenerates new fake commits based off limited information in thegenerated patches), those commits cannot be identified; instead it hasto fall back to a commit summary. Also, whenmerge.conflictStyle isset todiff3 orzdiff3, theapply backend will use "constructed mergebase" to label the content from the merge base, and thus provide noinformation about the merge base commit whatsoever.

Themerge backend works with the full commits on both sides of historyand thus has no such limitations.

Hooks

Theapply backend has not traditionally called the post-commit hook,while themerge backend has. Both have called the post-checkout hook,though themerge backend has squelched its output. Further, bothbackends only call the post-checkout hook with the starting pointcommit of the rebase, not the intermediate commits nor the finalcommit. In each case, the calling of these hooks was by accident ofimplementation rather than by design (both backends were originallyimplemented as shell scripts and happened to invoke other commandslikegitcheckout orgitcommit that would call the hooks). Bothbackends should have the same behavior, though it is not entirelyclear which, if any, is correct. We will likely make rebase stopcalling either of these hooks in the future.

Interruptability

Theapply backend has safety problems with an ill-timed interrupt; ifthe user presses Ctrl-C at the wrong time to try to abort the rebase,the rebase can enter a state where it cannot be aborted with asubsequentgitrebase--abort. Themerge backend does not appear tosuffer from the same shortcoming. (Seehttps://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/ fordetails.)

Commit Rewording

When a conflict occurs while rebasing, rebase stops and asks the userto resolve. Since the user may need to make notable changes whileresolving conflicts, after conflicts are resolved and the user has rungitrebase--continue, the rebase should open an editor and ask theuser to update the commit message. Themerge backend does this, whiletheapply backend blindly applies the original commit message.

Miscellaneous differences

There are a few more behavioral differences that most folks wouldprobably consider inconsequential but which are mentioned forcompleteness:

  • Reflog: The two backends will use different wording when describingthe changes made in the reflog, though both will make use of theword "rebase".

  • Progress, informational, and error messages: The two backendsprovide slightly different progress and informational messages.Also, the apply backend writes error messages (such as "Your fileswould be overwritten…​") to stdout, while the merge backend writesthem to stderr.

  • State directories: The two backends keep their state in differentdirectories under.git/

MERGE STRATEGIES

The merge mechanism (gitmerge andgitpull commands) allows thebackendmerge strategies to be chosen with-s option. Some strategiescan also take their own options, which can be passed by giving-X<option>arguments togitmerge and/orgitpull.

ort

This is the default merge strategy when pulling or merging onebranch. This strategy can only resolve two heads using a3-way merge algorithm. When there is more than one commonancestor that can be used for 3-way merge, it creates a mergedtree of the common ancestors and uses that as the referencetree for the 3-way merge. This has been reported to result infewer merge conflicts without causing mismerges by tests doneon actual merge commits taken from Linux 2.6 kerneldevelopment history. Additionally this strategy can detectand handle merges involving renames. It does not make use ofdetected copies. The name for this algorithm is an acronym("Ostensibly Recursive’s Twin") and came from the fact that itwas written as a replacement for the previous defaultalgorithm,recursive.

In the case where the path is a submodule, if the submodule commit used onone side of the merge is a descendant of the submodule commit used on theother side of the merge, Git attempts to fast-forward to thedescendant. Otherwise, Git will treat this case as a conflict, suggestingas a resolution a submodule commit that is descendant of the conflictingones, if one exists.

Theort strategy can take the following options:

ours

This option forces conflicting hunks to be auto-resolved cleanly byfavoringour version. Changes from the other tree that do notconflict with our side are reflected in the merge result.For a binary file, the entire contents are taken from our side.

This should not be confused with theours merge strategy, which does noteven look at what the other tree contains at all. It discards everythingthe other tree did, declaringour history contains all that happened in it.

theirs

This is the opposite ofours; note that, unlikeours, there isnotheirs merge strategy to confuse this merge option with.

ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol

Treats lines with the indicated type of whitespace change asunchanged for the sake of a three-way merge. Whitespacechanges mixed with other changes to a line are not ignored.See alsogit-diff[1]-b,-w,--ignore-space-at-eol, and--ignore-cr-at-eol.

  • Iftheir version only introduces whitespace changes to a line,our version is used;

  • Ifour version introduces whitespace changes buttheirversion includes a substantial change,their version is used;

  • Otherwise, the merge proceeds in the usual way.

renormalize

This runs a virtual check-out and check-in of all three stagesof any file which needs a three-way merge. This option ismeant to be used when merging branches with different cleanfilters or end-of-line normalization rules. See "Mergingbranches with differing checkin/checkout attributes" ingitattributes[5] for details.

no-renormalize

Disables therenormalize option. This overrides themerge.renormalize configuration variable.

find-renames[=<n>]

Turn on rename detection, optionally setting the similaritythreshold. This is the default. This overrides themerge.renames configuration variable.See alsogit-diff[1]--find-renames.

rename-threshold=<n>

Deprecated synonym forfind-renames=<n>.

no-renames

Turn off rename detection. This overrides themerge.renamesconfiguration variable.See alsogit-diff[1]--no-renames.

histogram

Deprecated synonym fordiff-algorithm=histogram.

patience

Deprecated synonym fordiff-algorithm=patience.

diff-algorithm=(histogram|minimal|myers|patience)

Use a different diff algorithm while merging, which can helpavoid mismerges that occur due to unimportant matching lines(such as braces from distinct functions). See alsogit-diff[1]--diff-algorithm. Note thatortdefaults todiff-algorithm=histogram, while regular diffscurrently default to thediff.algorithm config setting.

subtree[=<path>]

This option is a more advanced form ofsubtree strategy, wherethe strategy makes a guess on how two trees must be shifted tomatch with each other when merging. Instead, the specified pathis prefixed (or stripped from the beginning) to make the shape oftwo trees to match.

recursive

This is now a synonym forort. It was an alternativeimplementation until v2.49.0, but was redirected to meanortin v2.50.0. The previous recursive strategy was the defaultstrategy for resolving two heads from Git v0.99.9k untilv2.33.0.

resolve

This can only resolve two heads (i.e. the current branchand another branch you pulled from) using a 3-way mergealgorithm. It tries to carefully detect criss-crossmerge ambiguities. It does not handle renames.

octopus

This resolves cases with more than two heads, but refuses to doa complex merge that needs manual resolution. It isprimarily meant to be used for bundling topic branchheads together. This is the default merge strategy whenpulling or merging more than one branch.

ours

This resolves any number of heads, but the resulting tree of themerge is always that of the current branch head, effectivelyignoring all changes from all other branches. It is meant tobe used to supersede old development history of sidebranches. Note that this is different from the-Xours option totheort merge strategy.

subtree

This is a modifiedort strategy. When merging trees A andB, if B corresponds to a subtree of A, B is first adjusted tomatch the tree structure of A, instead of reading the trees atthe same level. This adjustment is also done to the commonancestor tree.

With the strategies that use 3-way merge (including the default,ort),if a change is made on both branches, but later reverted on one of thebranches, that change will be present in the merged result; some people findthis behavior confusing. It occurs because only the heads and the merge baseare considered when performing a merge, not the individual commits. The mergealgorithm therefore considers the reverted change as no change at all, andsubstitutes the changed version instead.

NOTES

You should understand the implications of usinggitrebase on arepository that you share. See also RECOVERING FROM UPSTREAM REBASEbelow.

When the rebase is run, it will first execute apre-rebase hook if oneexists. You can use this hook to do sanity checks and reject the rebaseif it isn’t appropriate. Please see the templatepre-rebase hook scriptfor an example.

Upon completion,<branch> will be the current branch.

INTERACTIVE MODE

Rebasing interactively means that you have a chance to edit the commitswhich are rebased. You can reorder the commits, and you canremove them (weeding out bad or otherwise unwanted patches).

The interactive mode is meant for this type of workflow:

  1. have a wonderful idea

  2. hack on the code

  3. prepare a series for submission

  4. submit

where point 2. consists of several instances of

a) regular use

  1. finish something worthy of a commit

  2. commit

b) independent fixup

  1. realize that something does not work

  2. fix that

  3. commit it

Sometimes the thing fixed in b.2. cannot be amended to the not-quiteperfect commit it fixes, because that commit is buried deeply in apatch series. That is exactly what interactive rebase is for: use itafter plenty of "a"s and "b"s, by rearranging and editingcommits, and squashing multiple commits into one.

Start it with the last commit you want to retain as-is:

git rebase -i <after-this-commit>

An editor will be fired up with all the commits in your current branch(ignoring merge commits), which come after the given commit. You canreorder the commits in this list to your heart’s content, and you canremove them. The list looks more or less like this:

pick deadbee The oneline of this commitpick fa1afe1 The oneline of the next commit...

The oneline descriptions are purely for your pleasure;git rebase willnot look at them but at the commit names ("deadbee" and "fa1afe1" in thisexample), so do not delete or edit the names.

By replacing the command "pick" with the command "edit", you can tellgitrebase to stop after applying that commit, so that you can editthe files and/or the commit message, amend the commit, and continuerebasing.

To interrupt the rebase (just like an "edit" command would do, but withoutcherry-picking any commit first), use the "break" command.

If you just want to edit the commit message for a commit, replace thecommand "pick" with the command "reword".

To drop a commit, replace the command "pick" with "drop", or justdelete the matching line.

If you want to fold two or more commits into one, replace the command"pick" for the second and subsequent commits with "squash" or "fixup".If the commits had different authors, the folded commit will beattributed to the author of the first commit. The suggested commitmessage for the folded commit is the concatenation of the firstcommit’s message with those identified by "squash" commands, omitting themessages of commits identified by "fixup" commands, unless "fixup -c"is used. In that case the suggested commit message is only the messageof the "fixup -c" commit, and an editor is opened allowing you to editthe message. The contents (patch) of the "fixup -c" commit are stillincorporated into the folded commit. If there is more than one "fixup -c"commit, the message from the final one is used. You can also use"fixup -C" to get the same behavior as "fixup -c" except without openingan editor.

gitrebase will stop when "pick" has been replaced with "edit" orwhen a command fails due to merge errors. When you are done editingand/or resolving conflicts you can continue withgitrebase--continue.

For example, if you want to reorder the last 5 commits, such that whatwasHEAD~4 becomes the newHEAD. To achieve that, you would callgitrebase like this:

$ git rebase -i HEAD~5

And move the first patch to the end of the list.

You might want to recreate merge commits, e.g. if you have a historylike this:

           X            \         A---M---B        /---o---O---P---Q

Suppose you want to rebase the side branch starting at "A" to "Q". Makesure that the currentHEAD is "B", and call

$ git rebase -i -r --onto Q O

Reordering and editing commits usually creates untested intermediatesteps. You may want to check that your history editing did not breakanything by running a test, or at least recompiling at intermediatepoints in history by using the "exec" command (shortcut "x"). You maydo so by creating a todo list like this one:

pick deadbee Implement feature XXXfixup f1a5c00 Fix to feature XXXexec makepick c0ffeee The oneline of the next commitedit deadbab The oneline of the commit afterexec cd subdir; make test...

The interactive rebase will stop when a command fails (i.e. exits withnon-0 status) to give you an opportunity to fix the problem. You cancontinue withgitrebase--continue.

The "exec" command launches the command in a shell (the default one, usually/bin/sh), so you can use shell features (like "cd", ">", ";" …​). The commandis run from the root of the working tree.

$ git rebase -i --exec "make test"

This command lets you check that intermediate commits are compilable.The todo list becomes like that:

pick 5928aea oneexec make testpick 04d0fda twoexec make testpick ba46169 threeexec make testpick f4593f9 fourexec make test

SPLITTING COMMITS

In interactive mode, you can mark commits with the action "edit". However,this does not necessarily mean thatgitrebase expects the result of thisedit to be exactly one commit. Indeed, you can undo the commit, or you canadd other commits. This can be used to split a commit into two:

  • Start an interactive rebase withgitrebase-i<commit>^, where<commit> is the commit you want to split. In fact, any commit rangewill do, as long as it contains that commit.

  • Mark the commit you want to split with the action "edit".

  • When it comes to editing that commit, executegitresetHEAD^. Theeffect is that theHEAD is rewound by one, and the index follows suit.However, the working tree stays the same.

  • Now add the changes to the index that you want to have in the firstcommit. You can usegitadd (possibly interactively) orgitgui (or both) to do that.

  • Commit the now-current index with whatever commit message is appropriatenow.

  • Repeat the last two steps until your working tree is clean.

  • Continue the rebase withgitrebase--continue.

If you are not absolutely sure that the intermediate revisions areconsistent (they compile, pass the testsuite, etc.) you should usegitstash to stash away the not-yet-committed changesafter each commit, test, and amend the commit if fixes are necessary.

RECOVERING FROM UPSTREAM REBASE

Rebasing (or any other form of rewriting) a branch that others havebased work on is a bad idea: anyone downstream of it is forced tomanually fix their history. This section explains how to do the fixfrom the downstream’s point of view. The real fix, however, would beto avoid rebasing the upstream in the first place.

To illustrate, suppose you are in a situation where someone develops asubsystem branch, and you are working on atopic that is dependenton thissubsystem. You might end up with a history like thefollowing:

    o---o---o---o---o---o---o---o  master \  o---o---o---o---o  subsystem   \    *---*---*  topic

Ifsubsystem is rebased againstmaster, the following happens:

    o---o---o---o---o---o---o---o  master \ \  o---o---o---o---o  o'--o'--o'--o'--o'  subsystem   \    *---*---*  topic

If you now continue development as usual, and eventually mergetopictosubsystem, the commits fromsubsystem will remain duplicated forever:

    o---o---o---o---o---o---o---o  master \ \  o---o---o---o---o  o'--o'--o'--o'--o'--M subsystem   \     /    *---*---*-..........-*--*  topic

Such duplicates are generally frowned upon because they clutter uphistory, making it harder to follow. To clean things up, you need totransplant the commits ontopic to the newsubsystem tip, i.e.,rebasetopic. This becomes a ripple effect: anyone downstream fromtopic is forced to rebase too, and so on!

There are two kinds of fixes, discussed in the following subsections:

Easy case: The changes are literally the same.

This happens if thesubsystem rebase was a simple rebase andhad no conflicts.

Hard case: The changes are not the same.

This happens if thesubsystem rebase had conflicts, or used--interactive to omit, edit, squash, or fixup commits; orif the upstream used one ofcommit--amend,reset, ora full history rewriting command likefilter-repo.

The easy case

Only works if the changes (patch IDs based on the diff contents) onsubsystem are literally the same before and after the rebasesubsystem did.

In that case, the fix is easy becausegit rebase knows to skipchanges that are already present in the new upstream (unless--reapply-cherry-picks is given). So if you say(assuming you’re ontopic)

    $ git rebase subsystem

you will end up with the fixed history

    o---o---o---o---o---o---o---o  master \  o'--o'--o'--o'--o'  subsystem   \    *---*---*  topic

The hard case

Things get more complicated if thesubsystem changes do not exactlycorrespond to the ones before the rebase.

Note
While an "easy case recovery" sometimes appears to be successful even in the hard case, it may have unintended consequences. For example, a commit that was removed viagitrebase--interactive will beresurrected!

The idea is to manually tellgitrebase "where the oldsubsystemended and yourtopic began", that is, what the old merge basebetween them was. You will have to find a way to name the last commitof the oldsubsystem, for example:

  • With thesubsystem reflog: aftergitfetch, the old tip ofsubsystem is atsubsystem@{1}. Subsequent fetches willincrease the number. (Seegit-reflog[1].)

  • Relative to the tip oftopic: knowing that yourtopic has threecommits, the old tip ofsubsystem must betopic~3.

You can then transplant the oldsubsystem..topic to the new tip bysaying (for the reflog case, and assuming you are ontopic already):

    $ git rebase --onto subsystem subsystem@{1}

The ripple effect of a "hard case" recovery is especially bad:everyone downstream fromtopic will now have to perform a "hardcase" recovery too!

REBASING MERGES

The interactive rebase command was originally designed to handleindividual patch series. As such, it makes sense to exclude mergecommits from the todo list, as the developer may have merged thethen-currentmaster while working on the branch, only to rebaseall the commits ontomaster eventually (skipping the mergecommits).

However, there are legitimate reasons why a developer may want torecreate merge commits: to keep the branch structure (or "committopology") when working on multiple, inter-related branches.

In the following example, the developer works on a topic branch thatrefactors the way buttons are defined, and on another topic branchthat uses that refactoring to implement a "Report a bug" button. Theoutput ofgitlog--graph--format=%s-5 may look like this:

*   Merge branch 'report-a-bug'|\| * Add the feedback button* | Merge branch 'refactor-button'|\ \| |/| * Use the Button class for all buttons| * Extract a generic Button class from the DownloadButton one

The developer might want to rebase those commits to a newermasterwhile keeping the branch topology, for example when the first topicbranch is expected to be integrated intomaster much earlier than thesecond one, say, to resolve merge conflicts with changes to theDownloadButton class that made it intomaster.

This rebase can be performed using the--rebase-merges option.It will generate a todo list looking like this:

label onto# Branch: refactor-buttonreset ontopick 123456 Extract a generic Button class from the DownloadButton onepick 654321 Use the Button class for all buttonslabel refactor-button# Branch: report-a-bugreset refactor-button # Use the Button class for all buttonspick abcdef Add the feedback buttonlabel report-a-bugreset ontomerge -C a1b2c3 refactor-button # Merge 'refactor-button'merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'

In contrast to a regular interactive rebase, there arelabel,resetandmerge commands in addition topick ones.

Thelabel command associates a label with the current HEAD when thatcommand is executed. These labels are created as worktree-local refs(refs/rewritten/<label>) that will be deleted when the rebasefinishes. That way, rebase operations in multiple worktrees linked tothe same repository do not interfere with one another. If thelabelcommand fails, it is rescheduled immediately, with a helpful message howto proceed.

Thereset command resets the HEAD, index and worktree to the specifiedrevision. It is similar to anexecgitreset--hard<label>, butrefuses to overwrite untracked files. If thereset command fails, it isrescheduled immediately, with a helpful message how to edit the todo list(this typically happens when areset command was inserted into the todolist manually and contains a typo).

Themerge command will merge the specified revision(s) into whateveris HEAD at that time. With-C<original-commit>, the commit message ofthe specified merge commit will be used. When the-C is changed toa lower-case-c, the message will be opened in an editor after asuccessful merge so that the user can edit the message.

If amerge command fails for any reason other than merge conflicts (i.e.when the merge operation did not even start), it is rescheduled immediately.

By default, themerge command will use theort merge strategy forregular merges, andoctopus for octopus merges. One can specify adefault strategy for all merges using the--strategy argument wheninvoking rebase, or can override specific merges in the interactivelist of commands by using anexec command to callgitmergeexplicitly with a--strategy argument. Note that when callinggitmerge explicitly like this, you can make use of the fact that thelabels are worktree-local refs (the refrefs/rewritten/onto wouldcorrespond to the labelonto, for example) in order to refer to thebranches you want to merge.

Note: the first command (labelonto) labels the revision onto whichthe commits are rebased; The nameonto is just a convention, as a nodto the--onto option.

It is also possible to introduce completely new merge commits from scratchby adding a command of the formmerge<merge-head>. This form willgenerate a tentative commit message and always open an editor to let theuser edit it. This can be useful e.g. when a topic branch turns out toaddress more than a single concern and wants to be split into two oreven more topic branches. Consider this todo list:

pick 192837 Switch from GNU Makefiles to CMakepick 5a6c7e Document the switch to CMakepick 918273 Fix detection of OpenSSL in CMakepick afbecd http: add support for TLS v1.3pick fdbaec Fix detection of cURL in CMake on Windows

The one commit in this list that is not related to CMake may very wellhave been motivated by working on fixing all those bugs introduced byswitching to CMake, but it addresses a different concern. To split thisbranch into two topic branches, the todo list could be edited like this:

label ontopick afbecd http: add support for TLS v1.3label tlsv1.3reset ontopick 192837 Switch from GNU Makefiles to CMakepick 918273 Fix detection of OpenSSL in CMakepick fdbaec Fix detection of cURL in CMake on Windowspick 5a6c7e Document the switch to CMakelabel cmakereset ontomerge tlsv1.3merge cmake

CONFIGURATION

Everything below this line in this section is selectively includedfrom thegit-config[1] documentation. The content is the sameas what’s found there:

rebase.backend

Default backend to use for rebasing. Possible choices areapply ormerge. In the future, if the merge backend gainsall remaining capabilities of the apply backend, this settingmay become unused.

rebase.stat

Whether to show a diffstat of what changed upstream since the lastrebase. False by default.

rebase.autoSquash

If set to true, enable the--autosquash option ofgit-rebase[1] by default for interactive mode.This can be overridden with the--no-autosquash option.

rebase.autoStash

When set to true, automatically create a temporary stash entrybefore the operation begins, and apply it after the operationends. This means that you can run rebase on a dirty worktree.However, use with care: the final stash application after asuccessful rebase might result in non-trivial conflicts.This option can be overridden by the--no-autostash and--autostash options ofgit-rebase[1].Defaults to false.

rebase.updateRefs

If set to true enable--update-refs option by default.

rebase.missingCommitsCheck

If set to "warn", git rebase -i will print a warning if somecommits are removed (e.g. a line was deleted), however therebase will still proceed. If set to "error", it will printthe previous warning and stop the rebase,git rebase--edit-todo can then be used to correct the error. If set to"ignore", no checking is done.To drop a commit without warning or error, use thedropcommand in the todo list.Defaults to "ignore".

rebase.instructionFormat

A format string, as specified ingit-log[1], to be used for thetodo list during an interactive rebase. The format willautomatically have the commit hash prepended to the format.

rebase.abbreviateCommands

If set to true,gitrebase will use abbreviated command names in thetodo list resulting in something like this:

p deadbee The oneline of the commitp fa1afe1 The oneline of the next commit...

instead of:

pick deadbee The oneline of the commitpick fa1afe1 The oneline of the next commit...

Defaults to false.

rebase.rescheduleFailedExec

Automatically rescheduleexec commands that failed. This only makessense in interactive mode (or when an--exec option was provided).This is the same as specifying the--reschedule-failed-exec option.

rebase.forkPoint

If set to false set--no-fork-point option by default.

rebase.rebaseMerges

Whether and how to set the--rebase-merges option by default. Canberebase-cousins,no-rebase-cousins, or a boolean. Setting totrue or tono-rebase-cousins is equivalent to--rebase-merges=no-rebase-cousins, setting torebase-cousins isequivalent to--rebase-merges=rebase-cousins, and setting to false isequivalent to--no-rebase-merges. Passing--rebase-merges on thecommand line, with or without an argument, overrides anyrebase.rebaseMerges configuration.

rebase.maxLabelLength

When generating label names from commit subjects, truncate the names tothis length. By default, the names are truncated to a little less thanNAME_MAX (to allow e.g..lock files to be written for thecorresponding loose refs).

sequence.editor

Text editor used bygitrebase-i for editing the rebase instruction file.The value is meant to be interpreted by the shell when it is used.It can be overridden by theGIT_SEQUENCE_EDITOR environment variable.When not configured, the default commit message editor is used instead.

GIT

Part of thegit[1] suite


[8]ページ先頭

©2009-2025 Movatter.jp