shithub: git9

Download patch

ref: deb7402afe2b7b4a047760442e1cfe6d1891bf47
parent: cfcc9e9a57d5daa0add014c83b23ae0eb0f77e84
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Dec 4 21:48:16 EST 2020

git/rebase: first cut of rebase implementation

Implement the basic version of git/rebase, handling
rewriting commits on one branch as though they were
based off a different branch.

Rebasing starts by finding the least common ancestor
of the two branches, and then replaying every commit
from the source branch on to the destination branch,
then renaming the source branch.

In the case of a conflict, the commits are dumped to
a temp file, and the rebase is paused until the user
either aborts the rebase or resolves the issue and
resumes the rebase.

--- a/git.1.man
+++ b/git.1.man
@@ -116,6 +116,14 @@
 .B git/merge
 .I theirs
 .PP
+.B git/rebase
+[
+.B -ar
+]
+[
+.B onto
+]
+.PP
 .B git/pull
 [
 .B -f
@@ -402,6 +410,19 @@
 takes two branches and merges them filewise using
 .I ape/diff3.
 The next commit made will be a merge commmit.
+
+.PP
+.B Git/rebase
+takes one branch and moves it onto another.
+On error, the remaining commits to rebase are
+saved, and can be resumed once the conflict is
+resolved using the
+.I -r
+option.
+If the rebase is to be aborted, the
+.I -a
+option will clean up the in progress rebase
+and reset the state of the branch.
 
 .PP
 .B Git/conf
--- a/import
+++ b/import
@@ -1,4 +1,4 @@
-#!/bin/rc
+#!/bin/rc -x
 rfork ne
 . /sys/lib/git/common.rc
 
@@ -69,7 +69,7 @@
 	rc -c '
 		echo applying $msg | sed 1q
 		date=`{seconds $date}
-		if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep '^patching file' | sed ''s/^patching file `(.*)''''/\1/''})
+		if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep ''^patching file'' | sed ''s/^patching file `(.*)''''/\1/''})
 			die ''patch failed''
 		for(f in $files){
 			if(test -e $f)
--- a/mkfile
+++ b/mkfile
@@ -26,6 +26,7 @@
 	merge\
 	pull\
 	push\
+	rebase\
 	revert\
 	rm
 
--- /dev/null
+++ b/rebase
@@ -1,0 +1,52 @@
+#!/bin/rc
+
+. /sys/lib/git/common.rc
+gitup
+
+flagfmt='a:abort, r:resume'; args='onto'
+eval `''{aux/getflags $*} || exec aux/usage
+
+tmp=_rebase.working
+if(! git/walk -q)
+	die dirty working tree
+if(~ $#abort 1){
+	if(! test -f .git/rebase.todo)
+		die no rebase to abort
+	src=`{cat .git/rebase.src}
+	rm -f .git/rebase.^(src dst todo)
+	git/branch $src
+	git/branch -d $tmp
+	exit
+}
+if(test -f .git/rebase.todo){
+	if(~ $#resume 0)
+		die rebase in progress
+	if(! ~ $#* 0)
+		exec aux/usage
+	src=`{cat .git/rebase.src}
+	dst=`{cat .git/rebase.dst}
+	commits=`{cat .git/rebase.todo}
+}
+if not{
+	if(! ~ $#* 1)
+		exec aux/usage
+	src=`{git/branch}
+	dst=`{git/query $1}
+	commits=`{git/query $onto $src @ .. $src}
+	## TODO: edit $commits here for -i
+}
+
+git/branch -nb $dst $tmp
+while(! ~ $#commmits 0){
+	c=$commits(1)
+	commits=$commits(2-)
+	if(! git/export $c | git/import){
+		echo $src > .git/rebase.src
+		echo $dst > .git/rebase.dst
+		echo $commits > .git/rebase.todo
+		die $c: fix and git/rebase -r
+	}
+}
+
+git/branch -nb $tmp $src
+git/branch -d $tmp