diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4d686f5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+export DEBUG := true
+export WANT_REMOTE := 1
+
+test:
+	./git-request-get < gitk-email.mbx 2>&1 | \
+	grep -e "ensure_remote: getting REMOTE = j6t and URL = https://github.com/j6t/gitk.git" \
+		-e "make_branch: getting BRANCH_NAME = mcepl-07012025 and HEAD = master" \
+		-e "main: DEST_ADDR= ~mcepl/git-test@lists.sr.ht, AUTHOR=Matěj Cepl <mcepl@cepl.eu>, BASE=c18400c6bb04f4e8875c1930db72ddd9b94649ca, HEAD=master"
diff --git a/git-request-get b/git-request-get
new file mode 100755
index 0000000..1f6edfa
--- /dev/null
+++ b/git-request-get
@@ -0,0 +1,186 @@
+#!/bin/sh
+# Requires: perl, sed, awk
+set -eux
+
+# Initialize internal variables
+DEBUG="${DEBUG:-}"
+WANT_REMOTE="${WANT_REMOTE:-"$(git config get --type int --default=0 git-request-get.wantRemote)"}"
+BASE=""
+HEAD=""
+DEST_ADDR=""
+
+usage() {
+    echo "usage: $(basename "$0") [-t ADDRTO] [-s] [-h] URL [HEAD] [BASE]" >&2
+    echo "Generate git-send-email messages from remote URL or from the email message"
+    echo "formatted by git-request-pull"
+    echo
+    echo "-t ADDRTO send emails to this email address"
+    exit 1
+}
+
+die() {
+    echo "$1" >&2
+    if test $# -gt 1
+    then
+        exit "$2"
+    else
+        exit 1
+    fi
+}
+
+log() {
+    echo "$1" >&2
+}
+
+parse_message() {
+    STR="$(perl -pe 'use MIME::QuotedPrint; $_=MIME::QuotedPrint::decode($_);')"
+    # Collect URL of the incoming repo
+    USTR="$(echo "$STR" | sed -n -e '/^are available in the Git repository at:/{n;n;p}')"
+    U="$(echo "$USTR" | awk '{print $1}')"
+
+    # Find the tip of the offered branch
+    # for you to fetch changes up to 102cd4d5c1818ecb5926dd538962f8b42c43b022:
+    B="$(echo "$STR" | awk '/^The following changes since commit / { print $NF }' | sed -e 's/[=:]*$//')"
+
+    E="$(echo "$USTR" | awk '{print $2}')"
+    if test -z "$E"
+    then
+        E="$(echo "$STR" | awk '/^for you to fetch changes up to / { print $NF }' | sed -e 's/[=:]*$//')"
+    fi
+    printf "%s^%s^%s" "$U" "$B" "$E"
+}
+
+ensure_remote () {
+    URL="$1"
+    REMSTR="$(git remote -v | awk -v url="$1" '(NR%2 == 1) && index($0, url) {print $1, $2}')"
+
+    if test -n "$REMSTR"
+    then
+        log "REMSTR found: ${REMSTR}\n"
+        REMOTE="$(echo "$REMSTR"|cut -d ' ' -f 1)"
+    else
+        # try to generate some good name for the remote
+        case "$URL" in
+        *github.com*|*gitlab.com*)
+            REMOTE="$(echo "$URL"|cut -d/ -f 4)"
+            ;;
+        *sr.ht*)
+            REMOTE="$(echo "$URL"|awk -F'[~/]' '{print $5}')"
+            ;;
+        *)
+            REMOTE="_4review"
+            ;;
+        esac
+        if test -z "$DEBUG"
+        then
+            git remote add "$REMOTE" "$URL"
+            git remote update "$REMOTE"
+        else
+            printf "ensure_remote: getting REMOTE = %s and URL = %s\n" "$REMOTE" "$URL" >&2
+        fi
+    fi
+
+    printf "%s" "$REMOTE"
+}
+
+#### main
+while getopts ":dht:" arg ; do
+    case $arg in
+        h)
+            usage
+            ;;
+        t)
+            DEST_ADDR="$OPTARG"
+            ;;
+        ?)
+            die "Invalid option: -${OPTARG}." 5
+            ;;
+    esac
+done
+
+shift $((OPTIND - 1))
+
+MASTER="master"
+if git rev-parse -q --verify main >/dev/null 2>&1
+then
+    MASTER="main"
+fi
+
+if test $# -lt 1
+then
+    PARSED_STR="$(parse_message)"
+    test -n "$PARSED_STR" || die "Not enough arguments and no message in stdin!" 2
+    URL="$(echo "$PARSED_STR"|cut -d '^' -f 1)"
+    BASE="$(echo "$PARSED_STR"|cut -d '^' -f 2)"
+    HEAD="$(echo "$PARSED_STR"|cut -d '^' -f 3)"
+# Ignore all command line arguments when stdin parsed
+else
+    if test $# -ge 1
+    then
+        URL="$1"
+    fi
+
+    if test -z "$URL"
+    then
+        die "Insufficient input: no parseable input or command line arguments." 3
+    fi
+
+    if test $# -ge 2
+    then
+        HEAD="$2"
+    else
+        HEAD="FETCH_HEAD"
+    fi
+
+    # find the base commit where PR roots in the default branch
+    if test $# -ge 3
+    then
+        BASE="$3"
+    fi
+fi
+
+if test "$WANT_REMOTE" -eq 1
+then
+    REMOTE="$(ensure_remote "$URL")"
+    if test -n "$HEAD" && ! git rev-parse -q --verify "$HEAD"
+    then
+        git rev-parse -q --verify "$REMOTE/$HEAD" || die "Cannot find $HEAD branch on the remote $REMOTE!" 4
+        HEAD="${REMOTE}/${HEAD}"
+    fi
+
+    BRANCH_NAME="$(git log --pretty="%aL" -1)-$(date '+%d%m%Y')"
+
+    if test -z "$DEBUG"
+    then
+        git branch "$BRANCH_NAME" "$HEAD"
+    else
+        printf "make_branch: getting BRANCH_NAME = %s and HEAD = %s\n" "$BRANCH_NAME" "$HEAD" >&2
+    fi
+else
+    git fetch "$URL"
+fi
+
+if test -z "$DEST_ADDR"
+then
+    DEST_ADDR="$(git config --default='' sendemail.to)"
+    test -z "$DEST_ADDR" && die "Unknown destination for the emails" 4
+fi
+
+test "$HEAD" = "FETCH_HEAD" && HEAD="$(git rev-parse -q --verify FETCH_HEAD)"
+
+ROOT="$(git merge-base "$MASTER" "$HEAD")"
+
+# commit is not part of our tree
+test "$ROOT" = "$HEAD" && die "Final commit cannot be included in our tree" 4
+
+test -z "$BASE" && BASE="$ROOT"
+
+test "$BASE" = "$HEAD" && die "No change observed" 1
+
+AUTHOR="$(git log --pretty="%an <%ae>" -1)"
+if test -z "$DEBUG"
+then
+    git send-email --to="$DEST_ADDR" --from="$AUTHOR" --no-annotate --no-cc --no-bcc --no-identity --quiet "${BASE}..${HEAD}"
+else
+    printf "main: DEST_ADDR= %s, AUTHOR=%s, BASE=%s, HEAD=%s\n" "$DEST_ADDR" "$AUTHOR" "$BASE" "$HEAD" 
+fi
