From f5ac3cc7c9efdc91670529f5702cfc72062b476b Mon Sep 17 00:00:00 2001 From: Trevor Date: Fri, 19 Aug 2022 05:33:15 -0700 Subject: [PATCH] git branch -update and -status tools (#425) --- bin/git-branch-status | 14 +++---- bin/git-branch-update | 94 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 9 deletions(-) create mode 100755 bin/git-branch-update diff --git a/bin/git-branch-status b/bin/git-branch-status index 5231f15d8d..7c4a0523a6 100755 --- a/bin/git-branch-status +++ b/bin/git-branch-status @@ -10,9 +10,8 @@ # git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads | \ -while read local remote -do - if [ -n "$remote" ]; then + while read local remote; do + if [[ -n $remote ]]; then git rev-list --left-right ${local}...${remote} -- 2>/dev/null >/tmp/git_upstream_status_delta || continue LEFT_AHEAD=$(grep -c '^<' /tmp/git_upstream_status_delta) RIGHT_AHEAD=$(grep -c '^>' /tmp/git_upstream_status_delta) @@ -30,11 +29,8 @@ do fi parent=$(git config branch.$local.parent) - if [[ -z $parent && $local != master ]]; then - parent=master - fi - - if [ -n "$parent" ]; then + + if [[ -n $parent ]]; then LEFT_PARENT=$(git rev-list --left-only --count $local...$parent) RIGHT_PARENT=$(git rev-list --right-only --count $local...$parent) if [ "$LEFT_PARENT" != 0 -a "$RIGHT_PARENT" != 0 ]; then @@ -52,7 +48,7 @@ do description=$(git config branch.$local.description) if [[ -z $description && $local != master ]]; then - description="git config branch.$local.description XXX" + description="(git config branch.$local.description 'TEST DESCRIPTION')" fi printf "%-15s%-30s%s\n" $local "$OFFSET$POFF" "$description" diff --git a/bin/git-branch-update b/bin/git-branch-update new file mode 100755 index 0000000000..b2372010c4 --- /dev/null +++ b/bin/git-branch-update @@ -0,0 +1,94 @@ +#!/bin/bash -e +# +# Automatically update configured branch dependencies. +# +# Configure with parent branch for local tracking, e.g.: +# git config branch.$branch.parent master +# +# Configure with description about what branch is for, e.g.: +# git config branch.$branch.description "Dependence changes" +# + +# TODO: Maybe make upstream origin default remote configurable. +origin=origin + +current=$(git branch --show-current) + +changes=$(git status -s) +if [[ -n $changes ]]; then + echo Working branch $current not clean, please revert/commit/stash before proceeding. + false +fi + +main=$(git config upstream.main) || true +if [[ -z $main ]]; then + echo "Upstream main branch not defined, please set with (e.g.) 'git config upstream.main master'" + false +fi + +upstream=$(git config upstream.remote) || true +if [[ -z $upstream ]]; then + echo "Upstream remote not defined, please set with (e.g.) 'git config upstream.remote faucet'" + false +fi + +echo Fetching upstream remote $upstream $main branch... +git fetch -q $upstream $main + +echo Fetching upstream origin... +git fetch -q $origin + +echo Updating local $main branch... +git switch -q $main +git merge -n -q $upstream/$main + +git for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads | \ +while read local remote; do + parent=$(git config branch.$local.parent) || true + + pmsg= + if [[ -z $parent ]]; then + pmsg=" (parent not configured, try e.g. 'git config branch.$local.parent $main')" + fi + + if [[ -z $pmsg && -z $remote ]]; then + pmsg=" (remote not configured, use `git push` to configure)" + fi + + echo Updating branch $local$pmsg... + git switch -q $local + + if [[ -n $parent ]]; then + mergebase=$(git merge-base $local $parent) + mergediff=$(git diff $parent $mergebase | wc -l) + if [[ $mergediff -ne 0 ]]; then + echo " Merge from local $parent..." + git merge -n -q $parent + fi + + masterdiff=$(git diff $parent | wc -l) || true + if [[ $local != $parent && $masterdiff -eq 0 ]]; then + echo " git branch -D $local # Branch is identical, consider deleting" + fi + fi + + if [[ -n $remote ]]; then + git rev-list --left-right ${local}...${remote} -- 2>/dev/null >/tmp/git_upstream_status_delta || true + LEFT_AHEAD=$(grep -c '^<' /tmp/git_upstream_status_delta) || true + RIGHT_AHEAD=$(grep -c '^>' /tmp/git_upstream_status_delta) || true + + if [[ $RIGHT_AHEAD != 0 ]]; then + echo " Disjoint upstream, merging down..." + git pull + fi + + difflines=$(git diff $remote | wc -l) + if [[ $LEFT_AHEAD != 0 ]]; then + echo " Push to upstream $remote..." + git push + fi + fi +done + +echo Returning to local branch $current... +git switch -q $current