Zusammenfassung: git merge-base --is-ancestor
testet, ob ein Commit ein Vorfahre eines anderen ist (wobei commits als eigene Vorfahren betrachtet werden, was eine besonders komische Form von Inzest ist, vielleicht :-)). Da ein Verzweigungsetikett nur von git merge
weitergeleitet werden kann, wenn der aktuelle Zweig (HEAD
) auf einen Commit verweist, der ein Vorgänger des anderen Commits ist, können wir damit ermitteln, ob git merge
einen schnellen Vorlauf ausführen kann.
Es sieht so aus, als wolltest du dies als Antwort gepostet haben, also habe ich es in einen funktionierenden Git-Alias umgewandelt, den du in deine globale Git-Konfiguration einfügen kannst.Der Alias ist ein bisschen lang und kompliziert, und es wäre wahrscheinlich am besten sein, nur cut-and-paste dieses Abschnitt in Ihrem git config-Alias:
canff = "!f() { if [ $# -gt 0 ]; then b=\"$1\"; git rev-parse -q --verify \"$b^{commit}\" >/dev/null || { printf \"%s: not a valid commit specifier\n\" \"$b\"; return 1; } else b=$(git rev-parse --symbolic-full-name --abbrev-ref @{u}) || return $?; fi; if git merge-base --is-ancestor HEAD \"$b\"; then echo \"merge with $b can fast-forward\"; else echo \"merge with $b cannot fast-forward\"; fi; }; f"
Hier ist das gleiche wie ein Shell-Skript geschrieben, in einem mehr lesbare Art und Weise, und einige Kommentare:
#! /bin/sh
#
# canff - test whether it is possible to fast-forward to
# a given commit (which may be a branch name). If given
# no arguments, find the upstream of the current (HEAD) branch.
# First, define a small function to print the upstream name
# of the current branch. If no upstream is set, this prints a
# message to stderr and returns with failure (nonzero).
upstream_name() {
git rev-parse --symbolic-full-name --abbrev-ref @{u}
}
# Now define a function to detect fast-forward-ability.
canff() {
local b # branch name or commit ID
if [ $# -gt 0 ]; then # at least 1 argument given
b="$1"
# make sure it is or can be converted to a commit ID.
git rev-parse -q --verify "$b^{commit}" >/dev/null || {
printf "%s: not a valid commit specifier\n" "$b"
return 1
}
else
# no arguments: find upstream, or bail out
b=$(upstream_name) || return $?
fi
# now test whether git merge --ff-only could succeed on $b
if git merge-base --is-ancestor HEAD "$b"; then
echo "merge with $b can fast-forward"
else
echo "merge with $b cannot fast-forward"
fi
}
das Shell-Skript braucht nur einen Hauptteil, es zu fahren, die der Aufruf von f
nach dem Alias ist. Der Alias selbst schaufelt einfach alles von canff
und upstream_name
in eine Zeile. Git's Konfigurationsdateiregeln erfordern dann, dass der gesamte Alias mit Anführungszeichen in Anführungszeichen gesetzt wird, was wiederum erfordert, dass alle internen Anführungszeichen in Backslash-Anführungszeichenfolgen konvertiert werden.
(Ich habe auch aus der local b
Aussage, da als Alias, das jedes Mal eine neue Instanz der Schale löst, also Variablenname Hygiene wird unwichtig.)
(es ist tatsächlich möglich, das schreiben Alias als mehrere Zeilen.Klicken Sie einfach jeder neuen Zeile Backslash voran.Jedoch ist dieser Alias so komplex, dass er auch auf diese Weise hässlich aussieht, also habe ich ihm nur eine große Zeile hinterlassen.)
Mögliche Duplikate von [Gibt es einen Git -merge --dry-run Option?] (http://stackoverflow.com/questions/501407/is-there-a-git-merge-dry-run-option) – Vishwanath