From 632b59a500a48c69348ec2067c314762bd84193f Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Mon, 27 Apr 2026 23:06:18 +0200 Subject: kinda seems to work --- bin/git-deli | 55 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'bin') diff --git a/bin/git-deli b/bin/git-deli index 6cca2cc..ca45002 100755 --- a/bin/git-deli +++ b/bin/git-deli @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # git-deli.sh: delinearized git workflows helper # @@ -11,17 +11,17 @@ OPTS_SPEC="\ git deli head [-b=] [-m=] [] [-s] -git deli go [-c] [-s] [-b=] [-m=] +git deli eat [-c] [-s] [-b=] [-m=] git deli commit ... git deli boundary [-d] git deli merge ... -git deli push [-f] -git deli pull +git deli push [-f] [] [] +git deli pull [] [] -- common options: h,help! show the help m,message!= specify the commit message - 'head' and 'go' options: + 'head' and 'eat' actions: b,branch!= start a new branch instead of using the target one s,set-boundary use the as a boundary for the new head c,create-head start a new head at and delinearize into it @@ -110,7 +110,7 @@ main() { shift # drop the command, we already got it case "$arg_command" in head) cmd_head "$arg_msg" "$arg_branch" "$arg_set_boundary" "$@" ;; - go) cmd_go "$arg_msg" "$arg_branch" "$@" ;; + eat) cmd_eat "$arg_msg" "$arg_branch" "$@" ;; commit) cmd_commit "$arg_msg" "$@" ;; boundary) cmd_boundary "$arg_delete" "$@" ;; merge) cmd_merge "$@" ;; @@ -156,14 +156,16 @@ cmd_head () { git reset --soft "$new_head" || die "git-reset failed to set the new HEAD" } -cmd_go () { +cmd_eat () { # we're squashing whatever has been done atop of a given head view + false } cmd_commit () { msg="$1" shift # TODO run a git commit with all extra args, THEN run head with the original commit + false } cmd_boundary () { @@ -173,6 +175,7 @@ cmd_boundary () { commit="$1" # TODO this adds or removes the "extra parents" to the head commit + false } cmd_merge () { @@ -279,6 +282,7 @@ stream_independent_commit_set () { } # usage: revision shas +# TODO: Binary files (match ^Binary in output, ask for all lines) deli_diff_to_source_lines () { awk -f ' BEGIN { @@ -300,10 +304,40 @@ match($0, /^@@ -([0-9]+),([0-9]+) /, matched) && file!="" { END { if(ranges!="") print(ranges, "--", file); } - ' | xargs -l git annotate -l "$1" | cut -d'\t' -f1 + ' \ + | xargs -l git annotate -l "$1" \ + | cut -d'\t' -f1 } -deli_commit () { +deli_eat_commit () { + delihead="$1" + target="$2" + # TODO insert bounds + parents=$( git diff ${DELI_DIFF_ARGS:-} -p "$delihead" "$target" | deli_diff_to_source_lines | sort | uniq | stream_independent_commit_set ) + # check if the parents are ok + for i in parents + do git merge-base --is-ancestor "$delihead" "$i" || die "changes in $target are based on $delihead" + done + set -- $parents + echo "sourcing commit $1..." >&2 + merged_tree="$1^{tree}" + shift + while test $# -gt 0 + do + echo "merging commit $1..." >&2 + merged_tree=$( git merge-tree --write-tree "$merged_tree" "$1^{tree}" || die "merging of the parents failed" ) + shift + done + + new_commit=$( + ( echo "tree $merged_tree" + for i in $parents + do echo "parent $i" + done + git cat-file commit "$target" | sed '/^$/bx; /^tree /d ; /^parent /d ; n ; :x' + ) | git hash-object -t commit --stdin -w || die "could not save new commit for tree $merged_tree" + ) + false } @@ -317,6 +351,7 @@ deli_commit () { # Given the heads merge cleanly, the algorithm actually reduces to a very # simple task: # +# - we do a normal merge (this must solve cleanly) # - all parents from the original 2 commits are combined and reduced to # independent set # - all bounds from the original 2 commits are also reduced to an independent @@ -326,6 +361,8 @@ deli_commit () { # (TODO does it make sense to check this?) # - we write out the new commit with all parents and all bounds # +# TODO tbh this should be the very same as doing the `eat` operation after a +# merge, but the eat would need to handle multiple parents correctly. deli_merge () { false -- cgit v1.2.3