From bde794827b895f1b7834688a7210ea04dd417fbc Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Wed, 29 Mar 2017 23:01:15 -0700 Subject: [PATCH] tg-tag.sh: allow choosing a consolidation commit's first parent When multiple branches are tagged, if there ends up being more than one independent head, a consolidation commit will be created and that will be tagged. The previously provided `--tree` option allows the tree used for that commit to be something other than the empty tree. Now, if one of the things being tagged is explicitly prefixed with a tilde ('~'), it will be forced to become the first parent of a consolidation commit if it's not the sole commit being tagged already and, in addition, if --tree has NOT been used then it's tree will become the default tree for any consolidation commit instead of the empty tree (but --tree is always respected if given). Signed-off-by: Kyle J. McKay --- README | 10 ++++++++++ tg-tag.sh | 31 ++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README b/README index 2466d51..f8f8d21 100644 --- a/README +++ b/README @@ -1452,6 +1452,16 @@ tg tag what's in the commit the newly created tag refers to). The argument to the ``--tree`` option may be any valid treeish. + If exactly one of the branches to be tagged is prefixed with a tilde + (``~``) it will be made the first parent of a consolidation commit if + it is not already the sole commit needing to be tagged. If ``--tree`` + is NOT used, its tree will also be used instead of the empty tree for + any new consolidation commit if one is created. Note that if + ``--tree`` is given explicitly it's tree is always used but that does + not in any way affect the choice of first parent. Beware that the + ``~`` may need to be quoted to prevent the shell from misinterpreting + it into something else. + All the options for creating a tag serve the same purpose as their Git equivalents except for two. The ``--refs`` option suppresses tag creation entirely and emits the "TOPGIT REFS" section that would have diff --git a/tg-tag.sh b/tg-tag.sh index 976077a..91558c8 100644 --- a/tg-tag.sh +++ b/tg-tag.sh @@ -412,6 +412,14 @@ tgcount=0 othercount=0 ignore= newlist= +firstprnt= +for arg in "$@"; do + case "$arg" in "~"?*) + [ -z "$firstprnt" ] || die "only one first parent may be specified with ~" + firstprnt="$(git rev-parse --verify --quiet "${arg#?}^0" -- 2>/dev/null)" && [ -n "$firstprnt" ] || + die "not a commit-ish: ${arg#?}" + esac +done while read -r obj typ ref && [ -n "$obj" -a -n "$typ" ]; do [ -n "$ref" -o "$typ" != "missing" ] || die "no such ref: ${obj%???}" case " $ignore " in *" $ref "*) continue; esac @@ -430,8 +438,8 @@ while read -r obj typ ref && [ -n "$obj" -a -n "$typ" ]; do fi done <<-EOT $({ - printf '%s\n' "$@" | sed 's/^\(.*\)$/\1^{} \1/' - printf '%s\n' "$@" | sed 's/^\(.*\)$/\1 \1/' + printf '%s\n' "$@" | sed 's/^~//; s/^\(.*\)$/\1^{} \1/' + printf '%s\n' "$@" | sed 's/^~//; s/^\(.*\)$/\1 \1/' } | git cat-file --batch-check='%(objectname) %(objecttype) %(rest)' 2>/dev/null || :) @@ -657,9 +665,22 @@ case "$allrefs${extrarefs:+ $extrarefs}" in die "failed: git merge-base --independent" ;; *) - parents="$allrefs^0" + if [ -n "$firstprnt" ]; then + parents="$(git rev-parse --quiet --verify "$allrefs^0" --)" || + die "failed: git rev-parse $allrefs^0" + else + parents="$allrefs^0" + fi ;; esac +if [ -n "$firstprnt" ]; then + oldparents="$parents" + parents="$firstprnt" + for acmt in $oldparents; do + [ "$acmt" = "$firstprnt" ] || parents="$parents $acmt" + done + unset oldparents +fi v_count_args pcnt $parents if [ $pcnt -eq 1 ]; then tagtarget="$parents" @@ -668,10 +689,10 @@ if [ $pcnt -eq 1 ]; then tagtarget= fi if [ -z "$tagtarget" ]; then - tagtree="$treeish" + tagtree="${treeish:-$firstprnt}" [ -n "$tagtree" ] || tagtree="$(git hash-object -t tree -w --stdin