Stacks of commits
Sapling provides first-class support for editing and manipulating stacks of commits.
Amend
You can edit any commit in your stack by going to that commit (via goto
), making the desired modifications, and then running amend
to edit the commit. Keep in mind that if you make a mistake, you can always Undo your changes!
$ sl
│ feature two
│
╭─╯ feature one
│
╷
~
$ echo "Add feature to myproject" >> myproject.cpp
# Apply changes to the current commit
$ sl amend
$ sl show .
...
diff --git a/myproject.cpp b/myproject.cpp
new file mode 100644
--- /dev/null
+++ b/myproject.cpp
@@ -0,0 +1,1 @@
+<amended feature one impl>
Fold
If you have a stack of commits, you can fold commits down into a single commit with the fold
command. You can either specify --from <commit id>
to specify a range of commits from your current commit to fold together or specify --exact <list of commit ids>
to specify exact adjacent commits to fold together.
$ sl
│ commit five
│
│ commit four
│
│ commit three
│
│ commit two
│
╭─╯ commit one
│
╷
~
$ sl fold --from ef7915cd2
# (equivalent to sl fold --exact ef7915cd2 b65a4efb1 bd057eb7f)
3 changesets folded
update complete
rebasing 5dbd8043fd7e "commit five"
merging myproject.cpp
5dbd8043fd7e -> debf0c562f6e "commit five"
$ sl
│ commit five
│
│ commit two+three+four
│
╭─╯ commit one
│
╷
~
Split
Use Sapling’s interactive editor interface to split the changes in one commit into two or more smaller commits.
$ sl
╭─╯ feature one + two
│
╷
~
# we want to split apart feature one and feature two
$ sl split
Select hunks to record - [x]=selected **=collapsed c: confirm q: abort
arrow keys: move/expand/collapse space: deselect ?: help
[~] diff --git a/myproject.cpp b/myproject.cpp
new file mode 100644
[~] @@ -0,0 +1,3 @@
[x] +<feature one>
[ ] +
[ ] +<feature two>
# <press c>
# <enter new commit message for first commit>
Done splitting? [yN] y
# remaining unselected changes go into second commit
# <enter new commit message for second commit>
$ sl
│ feature two
│
╭─╯ feature one
│
╷
~
Absorb
If you make changes while working at the top of a stack, the absorb
command allows you to automatically amend those changes to commits lower in the stack. If there is an unambiguous commit which introduced the edited lines, the absorb command will prompt to apply those changes to that commit.
$ sl
│ feature two
│
╭─╯ feature one
│
╷
~
# Edit part of "feature one", while we are on top of "feature two".
$ vim myproject.cpp
$ sl diff
diff --git a/myproject.cpp b/myproject.cpp
--- a/myproject.cpp
+++ b/myproject.cpp
@@ -1,3 +1,3 @@
-<feature one>
+<modified feature one>
<feature two>
# Absorb knows that commit 619efe4 introduced the edited lines.
$ sl absorb
showing changes for myproject.cpp
@@ -0,1 +0,1 @@
619efe4 -<feature one>
619efe4 +<modified feature one>
1 commit affected
619efe4 feature one
apply changes (yn)? **y**
619efe41024d -> cbf60a27cae4 "feature one"
a305c853a7b5 -> f656ac8c60c8 "feature two"
1 of 1 chunk applied
# Feature one commit now contains the modifications.
$ sl
│ feature two
│
╭─╯ feature one
│
╷
~
Amend --to
Sometimes absorb cannot predict an appropriate commit to apply changes to. In this case you can try the command sl amend --to
to specify exactly which commit to apply pending changes to.
$ sl
│ feature two
│
╭─╯ feature one
│
╷
~
# Add new file for feature one.
$ vim myproject2.cpp
$ sl addremove
adding myproject2.cpp
$ sl diff
diff --git a/myproject2.cpp b/myproject2.cpp
new file mode 100644
--- /dev/null
+++ b/myproject2.cpp
@@ -0,0 +1,1 @@
+<more pieces of feature one>
# Since the changes are in a new file, absorb can't predict
# which commit to apply any changes to.
$ sl absorb
nothing to absorb
# Use 'amend --to' to specify which commit to amend.
$ sl amend --to cbf60a27c
cbf60a27cae4 -> 768f3b26abc3 "feature one"
f656ac8c60c8 -> fe792a25079d "feature two"