ramas - manejo de git
GIT: ¿Cómo puedo evitar las fusiones de foxtrot en mi rama ''maestra''? (3)
Una combinación de foxtrot es una combinación donde ''origen / maestro'' se fusiona como un segundo padre (o posterior), de esta manera:
El commit ''D'' es una fusión de foxtrot porque ''origin / master'' es su segundo padre. Observe cómo el historial del primer padre de ''origin / master'' contiene commit ''B'' en este momento.
Pero en mi repositorio git necesito todas las fusiones que involucren ''origen / maestro'' para mantener ''origen / maestro'' como el primer padre. Desafortunadamente, a git no le importa el orden de los padres cuando evalúa si un commit es elegible para un avance rápido. Esto hace que el primer historial padre en mi rama maestra pierda a veces confirmaciones que solían estar allí (por ejemplo, salida de "git log --first-parent").
Esto es lo que sucede cuando se empuja la confirmación ''D'' del diagrama anterior:
¿Cómo puedo evitar este empuje? ¡El historial del primer padre de ''origin / master'' ya no contiene commit ''B'' después de que se empuja la combinación foxtrot!
Obviamente, no se pierden compromisos ni trabajo, es solo que en mi entorno realmente necesito "git log - first-parent" para ser un registro acumulativo estable de commits - si lo desea, una especie de "Write-Once Read-Many" "Base de datos (WORM). Tengo scripts y procesos que usan "git log - first-parent" para generar registros de cambios y notas de lanzamiento, así como para administrar las transiciones de tickets en mi sistema de tickets (JIRA). ¡Las fusiones de Foxtrot están rompiendo mis guiones!
¿Hay algún tipo de gancho previo a la recepción que pueda instalar en mis repositorios git para evitar que se empujen las combinaciones de foxtrot?
ps Los gráficos de confirmación en esta pregunta de stackoverflow se generaron usando http://bit-booster.com/graph.html .
Aquí hay un código de enlace que hará lo que está pidiendo:
pre-receive hook
#!/bin/sh
# Check to see if this is the first commit in the repository or not
if git rev-parse --verify HEAD >/dev/null 2>&1
then
# We compare our changes against the previous commit
against=HEAD^
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Redirect output to screen.
exec 1>&2
# Check to see if we have updated the master branch
if [ "$refname" eq "refs/heads/master" ];
then
# Output colors
red=''/033[0;31m'';
green=''/033[0;32m'';
yellow=''/033[0;33m'';
default=''/033[0;m'';
# personal touch :-)
echo "${red}"
echo " "
echo " |ZZzzz "
echo " | "
echo " | "
echo " |ZZzzz /^/ |ZZzzz "
echo " | |~~~| | "
echo " | |- -| / / "
echo " /^/ |[]+ | |^^^| "
echo " |^^^^^^^| | +[]| | | "
echo " | +[]|////////^/////////|^^^^^^^| "
echo " |+[]+ |~~~~~~~~~~~~~~~~~~| +[]| "
echo " | | [] /^/ [] |+[]+ | "
echo " | +[]+| [] || || [] | +[]+| "
echo " |[]+ | || || |[]+ | "
echo " |_______|------------------|_______| "
echo " "
echo " "
echo " ${green}You have just committed code ${red} "
echo " Your code ${yellow}is bad.!!! "
echo " ${red} Do not ever commit again "
echo " "
echo "${default}"
fi;
# set the exit code to 0 or 1 based upon your needs
# 0 = good to push
# 1 = exit without pushing.
exit 0;
El siguiente gancho previo a la recepción los bloqueará:
#/bin/bash
# Copyright (c) 2016 G. Sylvie Davies. http://bit-booster.com/
# Copyright (c) 2016 torek. http://.com/users/1256452/torek
# License: MIT license. https://opensource.org/licenses/MIT
while read oldrev newrev refname
do
if [ "$refname" = "refs/heads/master" ]; then
MATCH=`git log --first-parent --pretty=''%H %P'' $oldrev..$newrev |
grep $oldrev |
awk ''{ print /$2 }''`
if [ "$oldrev" = "$MATCH" ]; then
exit 0
else
echo "*** PUSH REJECTED! FOXTROT MERGE BLOCKED!!! ***"
exit 1
fi
fi
done
Si está utilizando Github / Gitlab / Bitbucket Cloud, es posible que deba considerar la creación de algún tipo de llamada en sus apis de estado de confirmación (aquí hay documentos api para: bitbucket , github ; no estoy seguro si gitlab tiene uno), porque usted no '' no tiene acceso a los ganchos de recepción previa, e incluso si lo hiciera, aún tendría que lidiar con personas que hacen clic en el botón "fusionar" directamente en la interfaz de usuario web de esos productos (en cuyo caso no hay "inserción") .
Con Bitbucket Server puedes instalar el complemento que creé .
Una vez que esté instalado, haga clic en "habilitar" en "Proteger el primer enlace principal" en la configuración de "enlace" de un repositorio dado:
Bloqueará las combinaciones de foxtrot mediante push y mediante el botón "merge" en la interfaz de usuario del servidor Bitbucket. Lo hace incluso si su licencia ha caducado, lo que convierte al "Protect First-Parent Hook" en un componente gratuito del complemento más grande.
Aquí hay un ejemplo de mi gancho de pre-recepción Bit-Booster "Protect First Parent" en acción:
$ git pull
$ git push
remote: *** PUSH REJECTED BY Protect-First-Parent HOOK ***
remote:
remote: Merge [1f70043b34d3] is not allowed. *Current* master must appear
remote: in the ''first-parent'' position of the subsequent commit. To see how
remote: master is merging into the wrong side (not as 1st parent), try this:
remote:
remote: git show --graph -s --pretty=''%h %d%n'' /
remote: 1f70043b34d3 1f70043b34d3~1 origin/master
remote:
remote: To fix, there are two traditional solutions:
remote:
remote: 1. (Preferred) rebase your branch:
remote:
remote: git rebase origin/master
remote: git push origin master
remote:
remote: 2. Redo the merge in the correct direction:
remote:
remote: git checkout master
remote: git reset --hard origin/master
remote: git merge --no-ff 1f70043b34d3eaedb750~1
remote: git push origin master
remote:
Para obtener más información sobre las combinaciones de Foxtrot bit-booster.blogspot.com/2016/02/no-foxtrots-allowed.html .
Escribí esto para proporcionar comentarios antes (también se necesita un gancho
pre-receive
).
Utilizo ganchos de
post-merge
y
pre-push
para esto.
No es posible evitar una fusión de foxtrot en commit-msg hook ya que la información para detectar uno está disponible solo después.
En el gancho
post-merge
, simplemente advierto.
En el gancho
pre-push
, tiro y bloqueo el empuje.
Consulte
d3f1821
("foxtrot: Agregar
d3f1821
para detectar fusiones de foxtrot", 2017-08-05).
~ / .git-hooks / helpers / foxtrot-merge-detector:
#!/bin/sh
#usage:
# foxtrot-merge-detector [<branch>]
#
# If foxtrot merge detected for branch (current branch if no branch),
# exit with 1.
# foxtrot merges:
# See http://bit-booster.blogspot.cz/2016/02/no-foxtrots-allowed.html
# https://.com/questions/35962754/git-how-can-i-prevent-foxtrot-merges-in-my-master-branch
remoteBranch=$(git rev-parse --abbrev-ref "$1"@{u} 2>/dev/null)
# no remote tracking branch, exit
if [[ -z "$remoteBranch" ]]; then
exit 0
fi
branch=$(git rev-parse --abbrev-ref "${1-@}" 2>/dev/null)
# branch commit does not cover remote branch commit, exit
if ! $(git merge-base --is-ancestor $remoteBranch $branch); then
exit 0
fi
remoteBranchCommit=$(git rev-parse $remoteBranch)
# branch commit is same as remote branch commit, exit
if [[ $(git rev-parse $branch) == $remoteBranchCommit ]]; then
exit 0
fi
# remote branch commit is first-parent of branch, exit
if [[ $(git log --first-parent --pretty=''%P'' $remoteBranchCommit..$branch | /
cut -d'' '' -f1 | /
grep $remoteBranchCommit | wc -l) -eq 1 ]]; then
exit 0
fi
# foxtrot merge detected if here
exit 1
Y luego úsalo como
gancho de pre-empuje:
#!/bin/sh
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]; then
# handle delete, do nothing
:
else
# ex $local_ref as "refs/heads/dev"
branch=$(git rev-parse --abbrev-ref "$local_ref")
~/.git-hooks/helpers/foxtrot-merge-detector "$branch"
# check exit code and exit if needed
exitcode=$?
if [ $exitcode -ne 0 ]; then
echo 1>&2 "fatal: foxtrot merge detected, aborting push"
echo 1>&2 "fatal: branch $branch"
exit $exitcode
fi
fi
done
post-fusión:
#!/bin/sh
~/.git-hooks/helpers/foxtrot-merge-detector
# check exit code and exit if needed
exitcode=$?
if [ $exitcode -ne 0 ]; then
echo -e " ${Yellow}WARNING:${None} foxtrot merge detected"
# swallow exit code
fi