the - git prune remote branches
¿Cuáles son las diferencias entre git remote prune, git prune, git fetch--prune, etc. (4)
Mi situación es esta ... alguien que trabaja en el mismo repositorio ha eliminado una rama de su repositorio local y remoto ...
La mayoría de las personas que han preguntado sobre este tipo de problema en el Desbordamiento de pila u otros sitios tienen el problema de las sucursales que aún aparecen en su lista de sucursales de seguimiento remoto git branch -a
en la parte inferior:
* master
develop
feature_blah
remotes/origin/master
remotes/origin/develop
remotes/origin/feature_blah
remotes/origin/random_branch_I_want_deleted
Sin embargo, en MI situación, la sucursal que no debería estar allí es local:
* master
develop
feature_blah
random_branch_I_want_deleted
remotes/origin/master
remotes/origin/develop
remotes/origin/feature_blah
Cuando hago algo de lo siguiente, no se elimina localmente:
$ git prune
También intenté:
$ git remote prune origin
$ git fetch --prune
Información más útil: cuando git remote show origin
así se ve
* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
master tracked
develop tracked
feature_blah tracked
other123 tracked
other444 tracked
other999 tracked
Local branches configured for ''git pull'':
develop merges with remote develop
feature_blah merges with remote other999
master merges with remote master
random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for ''git push'':
develop pushes to develop (local out of date)
master pushes to master (up to date)
feature_blah pushes to feature_blah(up to date)
Tenga en cuenta que solo se encuentra en la sección titulada Local branches configured for ''git pull'':
¿Por qué?
En el caso de que alguien estuviera interesado. Aquí hay un script de shell rápido que eliminará todas las sucursales locales que no se rastrean de forma remota. Una advertencia: esto eliminará cualquier rama que no se rastree de forma remota, independientemente de si se fusionó o no.
Si ustedes ven algún problema con esto, avísenme y lo arreglaré (etc., etc.)
Guárdelo en un archivo llamado git-rm-ntb
( git-rm-ntb
como sea) en PATH
y ejecute:
git-rm-ntb <remote1:optional> <remote2:optional> ...
clean()
{
REMOTES="$@";
if [ -z "$REMOTES" ]; then
REMOTES=$(git remote);
fi
REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
RBRANCHES=()
while read REMOTE; do
CURRBRANCHES=($(git ls-remote $REMOTE | awk ''{print $2}'' | grep ''refs/heads/'' | sed ''s:refs/heads/::''))
RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
done < <(echo "$REMOTES" )
[[ $RBRANCHES ]] || exit
LBRANCHES=($(git branch | sed ''s:/*::'' | awk ''{print $1}''))
for i in "${LBRANCHES[@]}"; do
skip=
for j in "${RBRANCHES[@]}"; do
[[ $i == $j ]] && { skip=1; echo -e "/033[32m Keeping $i /033[0m"; break; }
done
[[ -n $skip ]] || { echo -e "/033[31m $(git branch -D $i) /033[0m"; }
done
}
clean $@
No te culpo por frustrarte por esto. La mejor manera de mirar es esta. Hay potencialmente tres versiones de cada rama remota:
- La rama real en el repositorio remoto
- Su instantánea de esa rama localmente (almacenada en
refs/remotes/...
) - Y una sucursal local que podría estar rastreando la sucursal remota.
Vamos a empezar con git prune
. Esto elimina los objetos a los que ya no se hace referencia, no elimina las referencias. En tu caso, tienes una sucursal local. Eso significa que hay una referencia llamada random_branch_I_want_deleted
que se refiere a algunos objetos que representan el historial de esa rama. Entonces, por definición, git prune
random_branch_I_want_deleted
no eliminará random_branch_I_want_deleted
. En realidad, git prune
es una forma de eliminar los datos que se han acumulado en Git pero que no se hace referencia a nada. En general, no afecta tu vista de ninguna rama.
git remote prune origin
y git fetch --prune
operan en referencias bajo refs/remotes/...
(me referiré a éstas como referencias remotas). No afecta a las sucursales locales. La versión de git remote
es útil si solo desea eliminar las referencias remotas de un control remoto en particular. De lo contrario, los dos hacen exactamente lo mismo. Entonces, en resumen, git remote prune
git fetch --prune
y git fetch --prune
operan en el número 2 de arriba. Por ejemplo, si eliminó una rama utilizando la GUI web de git y no quiere que aparezca más en su lista de sucursales locales ( git branch -r
), este es el comando que debe usar.
Para eliminar una sucursal local, debe usar git branch -d
(o -D
si no está fusionada en ninguna parte). FWIW, no hay un comando git para eliminar automáticamente las ramas de seguimiento local si una rama remota desaparece.
Tenga en cuenta que se está arreglando una diferencia entre git remote --prune
y git fetch --prune
, con commit 10a6cc8 , por Tom Miller ( tmiller
) (para git 1.9 / 2.0, Q1 2014):
Cuando tenemos una rama de seguimiento remoto llamada "
frotz/nitfol
" de una búsqueda anterior, y lafrotz/nitfol
anterior ahora tiene una rama llamada "** frotz " **, lafetch
no podría eliminar "frotz/nitfol
" con una "git fetch --prune
"de la corriente ascendente.
git informaría al usuario de usar "git remote prune
" para solucionar el problema.
Entonces: cuando un repositorio ascendente tiene una rama ("frotz") con el mismo nombre que una jerarquía de rama ("frotz / xxx", una posible convención de nomenclatura de rama ), git remote --prune
tuvo éxito (en la limpieza del seguimiento remoto rama de tu repositorio), pero git fetch --prune
estaba fallando.
Ya no:
Cambie la forma en que funciona "
fetch --prune
" moviendo la operación de poda antes de la operación de extracción.
De esta manera, en lugar de advertir al usuario de un conflicto, lo soluciona automáticamente.
git remote prune
git fetch --prune
y git fetch --prune
hacen lo mismo: eliminar las referencias a las ramas que no existen en el control remoto, como dijiste. El segundo comando se conecta al remoto y recupera sus ramas actuales antes de podar.
Sin embargo, no toca las sucursales locales que ha extraído, que simplemente puede eliminar con
git branch -d random_branch_I_want_deleted
Reemplace -d
por -D
si la rama no se fusiona en otro lugar
git prune
hace algo diferente, purga objetos inalcanzables, esas confirmaciones que no son accesibles en ninguna rama o etiqueta, y por lo tanto ya no son necesarias.