remota ramas rama partir otra manejo fusionar crear conflictos git merge git-merge

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