From fef9a243f15138c9aead851ad8f3f89796204a4d Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 5 Dec 2022 10:08:01 +0100 Subject: [PATCH 1/7] git-backport-diff: Kill git-log after match found d0c8cbd7ac5bb has indeed made finding a match faster, but the downside is that the git-log process continues to run in the background even when we no longer consume its output. This is a problem particularly for large patch series, where git-backport-diff may thus spawn hundreds of subprocesses. We don't need the git-log process after we found a match, so make it a real job instead of an anonymous subprocess, which allows us to terminate it after we have found a match. Reported-by: Thomas Huth Fixes: d0c8cbd7ac5bb78c46d17e4fc04e77b6d3962baf --- git-backport-diff | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/git-backport-diff b/git-backport-diff index 2ae090f..d9a2aea 100755 --- a/git-backport-diff +++ b/git-backport-diff @@ -226,12 +226,21 @@ compare_git() do let cnt=$cnt+1; subj=${hashsubj:40} + + # We need to direct the git-log output through a FIFO so we + # get a git-log job that we can kill once we have found our + # match + git_fifo=$(mktemp -u --tmpdir 'backport-diff.XXXXXX') + mkfifo "$git_fifo" + downhash=${hashsubj:0:40} # A little bit hackish, but find the match by looking at upstream # subject lines, and using the newest one. Not all backports contain # the phrase "cherry-pick", so we can't really try and find the # upstream hash from that... uphash="" + git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}" >"$git_fifo" & + job_id=$(jobs -l | grep "\<$!\>" | sed -e 's/[^\[]*\[\([^\]]*\)\].*/\1/') while read uphashsubj do if [[ "${uphashsubj:40}" == "$subj" ]] @@ -239,7 +248,12 @@ compare_git() uphash=${uphashsubj:0:40} break fi - done < <(git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}") + done <"$git_fifo" + + # Ignore errors + kill %$job_id &>/dev/null || true + wait &> /dev/null + rm -f "$git_fifo" if [[ -n "$uphash" ]] then From 5c0aa17debb0cb04bafe92b28a1ddcf08cfa0042 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 5 Dec 2022 10:03:09 +0100 Subject: [PATCH 2/7] git-backport-diff: Add aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes a commit title changes across different versions of a series. This option allows the user to treat the new title as if it were the old one so we avoid false “[down]”s. (Not submitting to usptream because I feel like this is a misfeature, in a way.) --- git-backport-diff | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/git-backport-diff b/git-backport-diff index d9a2aea..ebca178 100755 --- a/git-backport-diff +++ b/git-backport-diff @@ -126,7 +126,9 @@ usage() { echo " git config backport-diff.summary" } -while getopts ":r:u:nd:phs:S" opt +declare -A aliases + +while getopts ":r:u:nd:phs:Sa:" opt do case $opt in r) range=$OPTARG @@ -149,6 +151,9 @@ do ;; S) summary='y' ;; + a) IFS='=' read -ra a <<< "$OPTARG" + aliases[${a[0]}]=${a[1]} + ;; h) usage exit ;; @@ -226,6 +231,10 @@ compare_git() do let cnt=$cnt+1; subj=${hashsubj:40} + if [ -n "${aliases[$subj]+_}" ] + then + subj=${aliases[$subj]} + fi # We need to direct the git-log output through a FIFO so we # get a git-log job that we can kill once we have found our From 0ddd339a1622b1dcb4b2ed18bf24b53bfcd087fe Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 5 Dec 2022 10:15:44 +0100 Subject: [PATCH 3/7] git-backport-diff: Something I have no idea what this is, but it is here, so commit (to) it. Signed-off-by: Hanna Reitz --- git-backport-diff | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/git-backport-diff b/git-backport-diff index ebca178..0f77d7f 100755 --- a/git-backport-diff +++ b/git-backport-diff @@ -210,7 +210,7 @@ elif git show-ref --quiet --verify refs/remotes/${upstream} then upstream_valid='y' # commit id -elif git rev-list --max-count=1 --quiet $upstream >/dev/null 2>&1 +elif git rev-list --max-count=1 --quiet $upstream -- >/dev/null 2>&1 then upstream_valid='y' fi @@ -230,7 +230,8 @@ compare_git() while read hashsubj do let cnt=$cnt+1; - subj=${hashsubj:40} + newsubj=${hashsubj:40} + subj=$newsubj if [ -n "${aliases[$subj]+_}" ] then subj=${aliases[$subj]} @@ -248,7 +249,7 @@ compare_git() # the phrase "cherry-pick", so we can't really try and find the # upstream hash from that... uphash="" - git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}" >"$git_fifo" & + git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}" -- >"$git_fifo" & job_id=$(jobs -l | grep "\<$!\>" | sed -e 's/[^\[]*\[\([^\]]*\)\].*/\1/') while read uphashsubj do @@ -266,12 +267,12 @@ compare_git() if [[ -n "$uphash" ]] then - numdiff=`diff -u <(git diff $uphash^! |egrep ^[-+])\ - <(git diff $downhash^! |egrep ^[-+])\ + numdiff=`diff -u <(git diff --diff-algorithm=patience $uphash^! |egrep ^[-+])\ + <(git diff --diff-algorithm=patience $downhash^! |egrep ^[-+])\ | egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true` # for contextual diff checking, we will ignore hashes and line number offsets - condiff=`diff -u <(git diff $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ - <(git diff $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ + condiff=`diff -u <(git diff --diff-algorithm=patience $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ + <(git diff --diff-algorithm=patience $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ | egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true` f="-" c="-" @@ -293,22 +294,22 @@ compare_git() then f=${bold}F${reset} showdiff=1 - printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$subj" + printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$newsubj" else - printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$subj" + printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$newsubj" fi if [[ $showdiff -eq 1 ]] then if [[ $diffprog == "meld" ]] then - label="--label=\"Patch #$cnt: $subj\" --label=\" \"" + label="--label=\"Patch #$cnt: $newsubj\" --label=\" \"" fi - subjlist[$cnt]=$subj + subjlist[$cnt]=$newsubj exe[$cnt]="${label} <(git show $uphash^!) <(git show $downhash^!) 2>/dev/null" shortexe[$cnt]="<(git show ${uphash:0:7}^\!) <(git show ${downhash:0:7}^\!)" fi else - printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$subj" + printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$newsubj" fi done < <(git log --pretty=tformat:"%H%s" --reverse $range) } From d9c095b6569c30dda5797b85cce3465b197e849b Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 5 Dec 2022 09:57:47 +0100 Subject: [PATCH 4/7] git-backport-diff: Add $DIFFOPTS Allow setting options for `git diff` via `$DIFFOPTS`. Signed-off-by: Hanna Reitz --- git-backport-diff | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/git-backport-diff b/git-backport-diff index 0f77d7f..c68b097 100755 --- a/git-backport-diff +++ b/git-backport-diff @@ -44,6 +44,10 @@ def_pause='y' def_sensitivity=0 def_summary='n' +if [ -z "${DIFFOPTS+x}" ]; then + DIFFOPTS= +fi + upstream=`git config backport-diff.upstream || true` diffprog=`git config backport-diff.diffprog || true` range=`git config backport-diff.range || true` @@ -267,12 +271,12 @@ compare_git() if [[ -n "$uphash" ]] then - numdiff=`diff -u <(git diff --diff-algorithm=patience $uphash^! |egrep ^[-+])\ - <(git diff --diff-algorithm=patience $downhash^! |egrep ^[-+])\ + numdiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^! |egrep ^[-+])\ + <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^! |egrep ^[-+])\ | egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true` # for contextual diff checking, we will ignore hashes and line number offsets - condiff=`diff -u <(git diff --diff-algorithm=patience $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ - <(git diff --diff-algorithm=patience $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ + condiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ + <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ | egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true` f="-" c="-" @@ -305,7 +309,7 @@ compare_git() label="--label=\"Patch #$cnt: $newsubj\" --label=\" \"" fi subjlist[$cnt]=$newsubj - exe[$cnt]="${label} <(git show $uphash^!) <(git show $downhash^!) 2>/dev/null" + exe[$cnt]="${label} <(git show $DIFFOPTS $uphash^!) <(git show $DIFFOPTS $downhash^!) 2>/dev/null" shortexe[$cnt]="<(git show ${uphash:0:7}^\!) <(git show ${downhash:0:7}^\!)" fi else From 8235ca6a6e068965b87fa02583e0d41b577fe2fa Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 5 Dec 2022 09:59:53 +0100 Subject: [PATCH 5/7] git-backport-diff: Replace egrep by grep -E The command `egrep` is now considered obsolete (and prints that to stderr), replace it by `grep -E`. Signed-off-by: Hanna Reitz --- git-backport-diff | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/git-backport-diff b/git-backport-diff index c68b097..31a3e97 100755 --- a/git-backport-diff +++ b/git-backport-diff @@ -271,13 +271,13 @@ compare_git() if [[ -n "$uphash" ]] then - numdiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^! |egrep ^[-+])\ - <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^! |egrep ^[-+])\ - | egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true` + numdiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^! |grep -E ^[-+])\ + <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^! |grep -E ^[-+])\ + | grep -E '^[-+]' | grep -E -v '^[-+]{3}' |wc -l || true` # for contextual diff checking, we will ignore hashes and line number offsets - condiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ - <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\ - | egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true` + condiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^\! |sed -e s/^@@.*@@//g |grep -E -v ^index |grep -E -v ^diff)\ + <(git diff --diff-algorithm=patience $DIFFOPTS $downhash^\!|sed -e s/^@@.*@@//g |grep -E -v ^index |grep -E -v ^diff)\ + | grep -E '^[-+]' | grep -E -v '^[-+]{3}'|wc -l || true` f="-" c="-" if [[ $sensitivity -gt 1 ]] From ebe807c99d84fad83ce0c2bb8ef11c07ccb1ec98 Mon Sep 17 00:00:00 2001 From: Hanna Czenczek Date: Fri, 17 Oct 2025 12:35:55 +0200 Subject: [PATCH 6/7] Add github/gitlab MR fetch scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given a numerical MR ID (and optionally the remote name), fetch the MR into a branch named “mr-${id}-v${version}”, where “version” starts at 1 (if no such branch exists so far), and then is incremented with each invocation (per MR). (Given a remote name, the pattern is “mr-${remote}-${id}-v${version}”.) Signed-off-by: Hanna Czenczek --- github-fetch-mr.sh | 26 ++++++++++++++++++++++++++ gitlab-fetch-mr.sh | 20 ++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100755 github-fetch-mr.sh create mode 100755 gitlab-fetch-mr.sh diff --git a/github-fetch-mr.sh b/github-fetch-mr.sh new file mode 100755 index 0000000..74952c6 --- /dev/null +++ b/github-fetch-mr.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +mr=$1 +remote="${2:-origin}" + +if [[ ! $mr =~ ^[0-9]+$ || $3 != "" ]]; then + echo "Usage: $0 [remote]" >&2 + exit 1 +fi + +if [ -n "$2" ]; then + infix="$2-" +else + infix="" +fi + +max_ver=$(git branch --list "mr-$infix$mr-v*" | sort | tail -n 1 | sed -e "s/^\*\? *mr-$infix$mr-v//") +branch="mr-$infix$mr-v$((max_ver + 1))" +cmd="git fetch $remote pull/$mr/head:$branch" + +echo "\$ $cmd" +$cmd + +git checkout $branch diff --git a/gitlab-fetch-mr.sh b/gitlab-fetch-mr.sh new file mode 100755 index 0000000..889d938 --- /dev/null +++ b/gitlab-fetch-mr.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e + +mr=$1 +remote="${2:-origin}" + +if [[ ! $mr =~ ^[0-9]+$ || $3 != "" ]]; then + echo "Usage: $0 [remote]" >&2 + exit 1 +fi + +max_ver=$(git branch --list "mr-$mr-v*" | grep "mr-$mr-v[0-9]\\+$" | sort | tail -n 1 | sed -e "s/^\*\? *mr-$mr-v//") +branch="mr-$mr-v$((max_ver + 1))" +cmd="git fetch $remote merge-requests/$mr/head:$branch" + +echo "\$ $cmd" +$cmd + +git checkout $branch From b935c3822d2461349758d3b51b77240acc568705 Mon Sep 17 00:00:00 2001 From: Hanna Czenczek Date: Fri, 17 Oct 2025 14:11:08 +0200 Subject: [PATCH 7/7] Add git-submit script This script helps to push updates to github MRs / gitlab PRs, using my usual local branch structure: * ${topic} as a clone of ${remote}/${topic} * ${topic}-next as my working branch * ${topic}-v* for previously pushed revisions Signed-off-by: Hanna Czenczek --- git-submit | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100755 git-submit diff --git a/git-submit b/git-submit new file mode 100755 index 0000000..507a2de --- /dev/null +++ b/git-submit @@ -0,0 +1,90 @@ +#!/usr/bin/ruby + +require 'shellwords' + +def die(msg, hint=nil) + $stderr.puts("\033[31;1m#{msg}\033[0m") + if hint + $stderr.puts("\033[1mHint: #{hint}\033[0m") + end + exit 1 +end + +def run(cmd) + puts("\033[1m$ #{cmd}\033[0m") + $stdout.write("OK? [y/n] ") + $stdout.flush + if gets.strip.downcase != 'y' + puts('(Aborting)') + exit 0 + end + system(cmd) +end + +def branch_exists?(name) + !`git branch --list #{name.shellescape}`.strip.empty? +end + +upstream_branch = 'main' +if !branch_exists?(upstream_branch) + upstream_branch = 'master' +end +if !branch_exists?(upstream_branch) + die('Found neither “main” nor “master”') +end + +next_branch = `git branch --show-current`.strip +if next_branch.empty? + die('Not on any branch') +end + +m = next_branch.match(/^(.*)-next$/) +if !m + die("Current branch (#{next_branch}) does not match the pattern `${topic}-next`") +end +base_branch = m[1] + +if !system("git merge-base --is-ancestor #{upstream_branch} #{next_branch}") + die("Upstream base branch #{upstream_branch} is not an ancestor of #{next_branch}") +end + +remote = `git config get branch.#{base_branch.shellescape}.remote`.strip +if remote.empty? + die("Base topic branch #{base_branch} has no remote info set", "Use git branch --set-upstream-to=${remote}/#{base_branch}") +end + +max_topic_ver = `git branch --color=never --list #{"#{base_branch}-v*".shellescape} | sort | tail -n 1`.strip.sub("#{base_branch}-v", '') +if max_topic_ver.empty? + max_topic_ver = 0 +else + max_topic_ver = Integer(max_topic_ver) +end +new_topic_ver = max_topic_ver + 1 + +puts <