Command: git move - arxanas/git-branchless Wiki

Description

The git-move command is used to move commits from one place to another in the commit graph. It's helpful when dealing with multiple divergent lines of work, such as in the Divergent development workflow.

It's intended to be a complete and improved replacement for git rebase (but not git rebase --interactive). Some of the improvements:

Usage

The basic usage for git move is to specify the source and destination commits, using the following options:

For example:

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 30s Create bar
┣━┓
┃ ◯ 55122556 23s Create baz
┃
◯ 87b20a4b 10s Create qux

$ git move -s 55122556 -d 87b20a4b
Attempting rebase in-memory...
[1/1] Committed as: c3841da6 Create baz
branchless: processing 1 rewritten commit
In-memory rebase succeeded.

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 41s Create bar
┃
◯ 87b20a4b 21s Create qux
┃
◯ c3841da6 1s Create baz

Moving branches

Note that the --source option is used to move all descendant commits. It probably won't do the right thing if you use it with a branch, because the branch points to the last commit in a stack, not the first commit. In the following example, notice how only the last commit on the xyzzy branch is moved:

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 14m Create bar
┣━┓
┃ ◯ 55122556 14m Create baz
┃ ┃
┃ ◯ 431d09d1 12m (xyzzy) Create xyzzy
┃
◯ 87b20a4b 14m Create qux

$ git move -s xyzzy -d 87b20a4b
Attempting rebase in-memory...
[1/1] Committed as: 68f58c59 Create xyzzy
branchless: processing 1 update: branch xyzzy
branchless: processing 1 rewritten commit
In-memory rebase succeeded.

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 14m Create bar
┣━┓
┃ ◯ 55122556 14m Create baz
┃
◯ 87b20a4b 14m Create qux
┃
◯ 68f58c59 2s (xyzzy) Create xyzzy

In this case, we want to use the -b/--base option. This option essentially means "move all of the commits starting from the base commit of that line of work:

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 16m Create bar
┣━┓
┃ ◯ 55122556 16m Create baz
┃ ┃
┃ ◯ 431d09d1 15m (xyzzy) Create xyzzy
┃
◯ 87b20a4b 16m Create qux

$ git move -b xyzzy -d 87b20a4b
Attempting rebase in-memory...
[1/2] Committed as: c985de45 Create baz
[2/2] Committed as: b98d18c9 Create xyzzy
branchless: processing 1 update: branch xyzzy
branchless: processing 2 rewritten commits
In-memory rebase succeeded.

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 17m Create bar
┃
◯ 87b20a4b 16m Create qux
┃
◯ c985de45 1s Create baz
┃
◯ b98d18c9 1s (xyzzy) Create xyzzy

It often helps to think of the -b option as meaning "branch". The technical meaning is that it calculates the "merge-base" between the source and destination commits.

Default options

If the --dest option is not set, then it defaults to --dest HEAD. This is to aid the common case of moving another set of commits on top of this one:

$ git move -s <commit>
...moves <commit> and its descendants on top of this one...

If neither the --source or --base options are set, then it defaults to --base HEAD. This is to aid the common case of moving the current commit stack somewhere else:

$ git move -d <commit>
...moves the current commit stack on top of <commit>...

Cycles

The Git commit graph is a directed acyclic graph, so cycles between commits cannot be formed. Consequently, you cannot move a commit on top of one of its descendant commits. If you try to do so, git move will produce an error and show the problematic cycle:

$ git sl
⋮
◇ 86bdeac0 50d (master) Revert "Update foo"
┃
● ec6d42e8 19m Create bar
┃
◯ 87b20a4b 18m Create qux
┃
◯ c985de45 2m Create baz
┃
◯ b98d18c9 2m (xyzzy) Create xyzzy

$ git move -s 87b20a4b -d xyzzy
This operation failed because it would introduce a cycle:
┌─ᐅ 87b20a4b Create qux
│   c985de45 Create baz
│   b98d18c9 Create xyzzy
└── 87b20a4b Create qux

This behavior may change in the future. (Another sensible option in this case would be to reorder the commits, rather than try to apply a commit on top of itself.)