Home Explore Blog CI



git

13th chunk of `Documentation/git-rebase.adoc`
bdd587bcfb9f9a189cccd50a48df770402586d35de13b3c70000000100000fa4

----------------------------------

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

--------------------
pick 5928aea one
exec make test
pick 04d0fda two
exec make test
pick ba46169 three
exec make test
pick f4593f9 four
exec make test
--------------------

SPLITTING COMMITS
-----------------

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

- Start an interactive rebase with `git rebase -i <commit>^`, where
  `<commit>` is the commit you want to split.  In fact, any commit range
  will 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, execute `git reset HEAD^`.  The
  effect is that the `HEAD` 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 first
  commit.  You can use `git add` (possibly interactively) or
  `git gui` (or both) to do that.

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

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

- Continue the rebase with `git rebase --continue`.

If you are not absolutely sure that the intermediate revisions are
consistent (they compile, pass the testsuite, etc.) you should use
`git stash` to stash away the not-yet-committed changes
after 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 have
based work on is a bad idea: anyone downstream of it is forced to
manually fix their history.  This section explains how to do the fix
from the downstream's point of view.  The real fix, however, would be
to avoid rebasing the upstream in the first place.

To illustrate, suppose you are in a situation where someone develops a
'subsystem' branch, and you are working on a 'topic' that is dependent
on this 'subsystem'.  You might end up with a history like the
following:

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

If 'subsystem' is rebased against 'master', 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 merge 'topic'
to 'subsystem', the commits from 'subsystem' 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 up
history, making it harder to follow.  To clean things up, you need to
transplant the commits on 'topic' to the new 'subsystem' tip, i.e.,
rebase 'topic'.  This becomes a ripple effect: anyone downstream from
'topic' 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 the 'subsystem' rebase was a simple rebase and
	had no conflicts.

Hard case: The changes are not the same.::

	This happens if the 'subsystem' rebase had conflicts, or used
	`--interactive` to omit, edit, squash, or fixup commits; or
	if the upstream used one of `commit --amend`, `reset`, or
	a full history rewriting command like
	https://github.com/newren/git-filter-repo[`filter-repo`].


The easy case
~~~~~~~~~~~~~

Only works if the changes (patch IDs based on the diff contents) on
'subsystem' are literally

Title: Recovering from Upstream Rebase and Splitting Commits
Summary
This section explains how to recover from an upstream rebase that has affected your local branch, and how to split commits into multiple ones using interactive rebase mode, including steps to rebase and transplant commits to a new base, and how to handle easy and hard cases where the changes are the same or different, respectively, due to conflicts, amend, reset, or history rewriting.