tutorial mac gui for español descargar commands git

mac - ¿Puedo “git pull-all” actualizar todas mis sucursales locales?



git repository (20)

Agregue este script a .profile en Mac OS X:

# Usage: # `git-pull-all` to pull all your local branches from origin # `git-pull-all remote` to pull all your local branches from a named remote function git-pull-all() { START=$(git symbolic-ref --short -q HEAD); for branch in $(git branch | sed ''s/^.//''); do git checkout $branch; git pull ${1:-origin} $branch || break; done; git checkout $START; }; function git-push-all() { git push --all ${1:-origin}; };

A menudo tengo al menos 3 sucursales remotas: master, puesta en escena y producción. Tengo 3 sucursales locales que rastrean esas sucursales remotas.

Actualizar todas mis sucursales locales es tedioso:

git fetch --all git rebase origin/master git checkout staging git rebase origin/staging git checkout production git rebase origin/production

Me encantaría poder simplemente hacer un "git pull-all", pero no he podido hacerlo funcionar. Parece hacer un "fetch - all", luego actualiza (avance rápido o fusiona) la rama de trabajo actual, pero no las otras sucursales locales.

Todavía estoy atascado manualmente cambiando a cada sucursal local y actualizando.



El comportamiento que describe para " pull --all es exactamente el esperado, aunque no es necesariamente útil. La opción se pasa a git fetch, que luego recupera todos los refs de todos los controles remotos, en lugar de solo el necesario; pull luego fusiona (o en su caso, vuelve a basarse) la única rama apropiada.

Si desea revisar otras sucursales, tendrá que revisarlas. Y sí, la fusión (y la reorganización) requieren absolutamente un árbol de trabajo, por lo que no se pueden hacer sin revisar las otras sucursales. Si lo desea, podría resumir los pasos descritos en un script / alias, aunque sugeriría unir los comandos con && para que, si uno de ellos falla, no intente seguir adelante.


El script de @larsmans, un poco mejorado:

#!/bin/sh set -x CURRENT=`git rev-parse --abbrev-ref HEAD` git fetch --all for branch in "$@"; do if ["$branch" -ne "$CURRENT"]; then git checkout "$branch" || exit 1 git rebase "origin/$branch" || exit 1 fi done git checkout "$CURRENT" || exit 1 git rebase "origin/$CURRENT" || exit 1

Esto, una vez que termina, deja la copia de trabajo desprotegida de la misma rama que estaba antes de que se llamara el script.

La versión git pull :

#!/bin/sh set -x CURRENT=`git rev-parse --abbrev-ref HEAD` git fetch --all for branch in "$@"; do if ["$branch" -ne "$CURRENT"]; then git checkout "$branch" || exit 1 git pull || exit 1 fi done git checkout "$CURRENT" || exit 1 git pull || exit 1


Este problema no está resuelto (todavía), al menos no fácilmente / sin scripting: vea esta publicación en la lista de correo de git de Junio ​​C Hamano, que explica la situación y ofrece una solución simple.

El razonamiento principal es que no deberías necesitar esto:

Con git que no es antiguo (es decir, v1.5.0 o más reciente), no hay razón para tener un "dev" local que simplemente rastree el control remoto. Si solo desea ver y ver, puede consultar la rama de seguimiento remoto directamente en un HEAD separado con " git checkout origin/dev ".

Lo que significa que los únicos casos que necesitamos para que sea conveniente para los usuarios son manejar estas sucursales locales que "rastrean" las remotas cuando tiene cambios locales, o cuando planea tener algunos.

Si tiene cambios locales en "dev" que están marcados para rastrear la eliminación de "dev", y si está en una rama diferente de "dev", no debemos hacer nada después de que " git fetch " actualice el seguimiento remoto " dev ". No avanzará de todos modos

La solicitud de una solución fue para una opción o script externo para eliminar las sucursales locales que siguen a las sucursales de seguimiento remoto, en lugar de mantenerlas actualizadas mediante el envío rápido, como el póster original solicitado.

Entonces, ¿qué hay de " git branch --prune --remote=<upstream> " que itera sobre las sucursales locales, y si

(1) no es la rama actual; y
(2) está marcado para rastrear alguna rama tomada del <upstream>; y
(3) no tiene ningún compromiso por sí mismo;

entonces quitar esa rama? " git remote --prune-local-forks <upstream> " también está bien; No me importa qué comando implementa la característica tanto.

Nota: a partir de git 2.10 no existe tal solución. Tenga en cuenta que el subcomando git fetch --prune y git fetch --prune tratan sobre la eliminación de la rama de seguimiento remoto para la rama que ya no existe en el control remoto, no sobre la eliminación de la rama local que realiza el seguimiento de la rama de seguimiento remoto (para la cual la rama de seguimiento remoto está en sentido ascendente rama).


Esto aún no es automático, ya que me gustaría que hubiera una opción para, y debería haber algunas comprobaciones para asegurarse de que esto solo pueda suceder con las actualizaciones de avance rápido (¡por eso es que hacer un pull manualmente es mucho más seguro!), Pero advertencias aparte puedes:

git fetch origin git update-ref refs/heads/other-branch origin/other-branch

para actualizar la posición de su sucursal local sin tener que revisarla.

Nota: perderá la posición actual de la rama y la moverá hacia donde se encuentra la rama de origen, lo que significa que si necesita fusionar perderá datos.


Hay muchas respuestas aceptables aquí, pero algunas de las tuberías pueden ser un poco opacas para los no iniciados. Aquí hay un ejemplo mucho más simple que se puede personalizar fácilmente:

$ cat ~/bin/git/git-update-all #!/bin/bash # Update all local branches, checking out each branch in succession. # Eventually returns to the original branch. Use "-n" for dry-run. git_update_all() { local run br br=$(git name-rev --name-only HEAD 2>/dev/null) [ "$1" = "-n" ] && shift && run=echo for x in $( git branch | cut -c3- ) ; do $run git checkout $x && $run git pull --ff-only || return 2 done [ ${#br} -gt 0 ] && $run git checkout "$br" } git_update_all "$@"

Si agrega ~/bin/git a su PATH (asumiendo que el archivo es ~/bin/git/git-update-all ), simplemente puede ejecutar:

$ git update-all


Hay muchas respuestas aquí, pero ninguna que use git-fetch para actualizar directamente la referencia local, que es mucho más simple que consultar sucursales, y más segura que git-update-ref .

Aquí utilizamos git-fetch para actualizar las ramas no actuales y git pull --ff-only para la rama actual. Eso:

  • No requiere retirar las sucursales.
  • Actualiza las sucursales solo si se pueden adelantar
  • Informará cuando no pueda avanzar rápidamente

Y aquí está:

#!/bin/bash currentbranchref="$(git symbolic-ref HEAD 2>&-)" git branch -r | grep -v '' -> '' | while read remotebranch do # Split <remote>/<branch> into remote and branchref parts remote="${remotebranch%%/*}" branchref="refs/heads/${remotebranch#*/}" if [ "$branchref" == "$currentbranchref" ] then echo "Updating current branch $branchref from $remote..." git pull --ff-only else echo "Updating non-current ref $branchref from $remote..." git fetch "$remote" "$branchref:$branchref" fi done

De la página del manual para git-fetch :

<refspec> The format of a <refspec> parameter is an optional plus +, followed by the source ref <src>, followed by a colon :, followed by the destination ref <dst>. The remote ref that matches <src> is fetched, and if <dst> is not empty string, the local ref that matches it is fast-forwarded using <src>. If the optional plus + is used, the local ref is updated even if it does not result in a fast-forward update.

Al especificar git fetch <remote> <ref>:<ref> (sin ningún + ) obtenemos un fetch que actualiza la referencia local solo cuando se puede avanzar rápidamente.

Nota : esto supone que las sucursales locales y remotas tienen el mismo nombre (y que desea realizar un seguimiento de todas las sucursales), en realidad debería usar información sobre qué sucursales locales tiene y para qué están configuradas.


No es tan difícil automatizar:

#!/bin/sh # Usage: fetchall.sh branch ... set -x git fetch --all for branch in "$@"; do git checkout "$branch" || exit 1 git rebase "origin/$branch" || exit 1 done


Para completar la respuesta de Matt Connolly, esta es una forma más segura de actualizar las referencias de sucursales locales que pueden ser enviadas rápidamente, sin consultar la sucursal. No actualiza las ramas que no pueden ser reenviadas rápidamente (es decir, que se han desviado) y no actualiza la rama que está actualmente activada (porque la copia de trabajo también debe actualizarse).

git fetch head="$(git symbolic-ref HEAD)" git for-each-ref --format="%(refname) %(upstream)" refs/heads | while read ref up; do if [ -n "$up" -a "$ref" != "$head" ]; then mine="$(git rev-parse "$ref")" theirs="$(git rev-parse "$up")" base="$(git merge-base "$ref" "$up")" if [ "$mine" != "$theirs" -a "$mine" == "$base" ]; then git update-ref "$ref" "$theirs" fi fi done


Parece que muchos otros han contribuido con soluciones similares, pero pensé en compartir lo que se me ocurrió e invitar a otros a contribuir. Esta solución tiene una salida colorida y agradable, maneja con gracia su directorio de trabajo actual, y es rápida porque no realiza ninguna comprobación y deja su directorio de trabajo intacto. Además, es solo un script de shell sin dependencias que no sea git. (solo probado en OSX hasta ahora)

#!/usr/bin/env bash gitup(){ RED=''/033[33;31m'' YELLO=''/033[33;33m'' GREEN=''/033[33;32m'' NC=''/033[0m'' # No Color HEAD=$(git rev-parse HEAD) CHANGED=$(git status --porcelain | wc -l) echo "Fetching..." git fetch --all --prune &>/dev/null for branch in `git for-each-ref --format=''%(refname:short)'' refs/heads`; do LOCAL=$(git rev-parse --quiet --verify $branch) if [ "$HEAD" = "$LOCAL" ] && [ $CHANGED -gt 0 ]; then echo -e "${YELLO}WORKING${NC}/t/t$branch" elif git rev-parse --verify --quiet $branch@{u}&>/dev/null; then REMOTE=$(git rev-parse --quiet --verify $branch@{u}) BASE=$(git merge-base $branch $branch@{u}) if [ "$LOCAL" = "$REMOTE" ]; then echo -e "${GREEN}OK${NC}/t/t$branch" elif [ "$LOCAL" = "$BASE" ]; then if [ "$HEAD" = "$LOCAL" ]; then git merge $REMOTE&>/dev/null else git branch -f $branch $REMOTE fi echo -e "${GREEN}UPDATED${NC}/t/t$branch" elif [ "$REMOTE" = "$BASE" ]; then echo -e "${RED}AHEAD${NC}/t/t$branch" else echo -e "${RED}DIVERGED${NC}/t/t$branch" fi else echo -e "${RED}NO REMOTE${NC}/t$branch" fi done }

https://github.com/davestimpert/gitup

Lo siento, parece que también he encontrado el mismo nombre que la otra herramienta anterior.


Si refs / heads / master puede ser reenviado rápidamente a refs / remotes / foo / master , la salida de

git merge-base refs/heads/master refs/remotes/foo/master

debe devolver el ID de SHA1 al que refs / heads / master apunta. Con esto, puede armar una secuencia de comandos que actualiza automáticamente todas las sucursales locales a las que no se les ha aplicado ninguna confirmación de desvío.

Este pequeño script de shell (lo llamé git-can-ff ) ilustra cómo se puede hacer.

#!/bin/sh set -x usage() { echo "usage: $(basename $0) <from-ref> <to-ref>" >&2 exit 2 } [ $# -ne 2 ] && usage FROM_REF=$1 TO_REF=$2 FROM_HASH=$(git show-ref --hash $FROM_REF) TO_HASH=$(git show-ref --hash $TO_REF) BASE_HASH=$(git merge-base $FROM_REF $TO_REF) if [ "$BASE_HASH" = "$FROM_HASH" -o / "$BASE_HASH" = "$FROM_REF" ]; then exit 0 else exit 1 fi


Si estás en Windows, puedes usar PyGitUp que es un clon de git-up para Python. Puede instalarlo usando pip con pip install --user git-up o mediante Scoop usando scoop install git-up

El


Solo publicando una respuesta actualizada. git-up ya no se mantiene y si lees la documentación, mencionan que la funcionalidad ahora está disponible en git .

A partir de Git 2.9, git pull --rebase --autostash hace básicamente lo mismo.

En consecuencia, si actualiza a Git 2.9 o posterior, puede usar este alias en lugar de instalar git-up:

git config --global alias.up ''pull --rebase --autostash''

También puede configurar esto para cada git pull partir de Git 2.9 también (gracias @VonC, consulte su respuesta here )

git config --global pull.rebase true git config --global rebase.autoStash true


Un guión que escribí para mi GitBash . Realiza lo siguiente:

  • De manera predeterminada, las fuentes desde el origen para todas las sucursales que están configuradas para rastrear el origen, le permite especificar un control remoto diferente si lo desea.
  • Si su rama actual está en un estado sucio, entonces esconde sus cambios e intentará restaurarlos al final.
  • Para cada sucursal local configurada para rastrear una sucursal remota:
    • git checkout branch
    • git pull origin
  • Finalmente, volverá a su estado original de bifurcación y restauración.

** Uso esto pero no lo he probado a fondo, uso bajo su propio riesgo. Vea un ejemplo de este script en un archivo .bash_alias here .

# Do a pull on all branches that are tracking a remote branches, will from origin by default. # If current branch is dirty, will stash changes and reply after pull. # Usage: pullall [remoteName] alias pullall=pullAll function pullAll (){ # if -h then show help if [[ $1 == ''-h'' ]] then echo "Description: Pulls new changes from upstream on all branches that are tracking remotes." echo echo "Usage: " echo "- Default: pullall" echo "- Specify upstream to pull from: pullall [upstreamName]" echo "- Help: pull-all -h" else # default remote to origin remote="origin" if [ $1 != "" ] then remote=$1 fi # list all branches that are tracking remote # git branch -vv : list branches with their upstreams # grep origin : keep only items that have upstream of origin # sed "s/^.."... : remove leading * # sed "s/^"..... : remove leading white spaces # cut -d" "..... : cut on spaces, take first item # cut -d splits on space, -f1 grabs first item branches=($(git branch -vv | grep $remote | sed "s/^[ *]*//" | sed "s/^[ /t]*//" | cut -d" " -f1)) # get starting branch name startingBranch=$(git rev-parse --abbrev-ref HEAD) # get starting stash size startingStashSize=$(git stash list | wc -l) echo "Saving starting branch state: $startingBranch" git stash # get the new stash size newStashSize=$(git stash list | wc -l) # for each branch in the array of remote tracking branches for branch in ${branches[*]} do echo "Switching to $branch" git checkout $branch echo "Pulling $remote" git pull $remote done echo "Switching back to $startingBranch" git checkout $startingBranch # compare before and after stash size to see if anything was stashed if [ "$startingStashSize" -lt "$newStashSize" ] then echo "Restoring branch state" git stash pop fi fi }


Un script ligeramente diferente que solo avanza rápidamente las ramas cuyos nombres coinciden con su rama ascendente. También actualiza la rama actual si es posible un avance rápido.

Asegúrese de que todas las sucursales de sus sucursales estén configuradas correctamente ejecutando git branch -vv . Establezca la rama en sentido ascendente con git branch -u origin/yourbanchname

Copiar-pegar en un archivo y chmod 755:

#!/bin/sh curbranch=$(git rev-parse --abbrev-ref HEAD) for branch in $(git for-each-ref refs/heads --format="%(refname:short)"); do upbranch=$(git config --get branch.$branch.merge | sed ''s:refs/heads/::''); if [ "$branch" = "$upbranch" ]; then if [ "$branch" = "$curbranch" ]; then echo Fast forwarding current branch $curbranch git merge --ff-only origin/$upbranch else echo Fast forwarding $branch with origin/$upbranch git fetch . origin/$upbranch:$branch fi fi done;


Uso el subcomando sync de hub para automatizar esto. Hub tiene un alias como git , por lo que el comando que escribo es:

git sync

Esto actualiza todas las sucursales locales que tienen una rama ascendente coincidente. De la página del manual:

  • Si la sucursal local no está actualizada, avance rápidamente;
  • Si la sucursal local contiene trabajo no pulido, adviértalo;
  • Si la rama parece fusionada y su rama ascendente se eliminó, elimínela.

También maneja los cambios no comprometidos de ocultación / desactivación en la rama actual.

Solía ​​usar una herramienta similar llamada git-up , pero ya no se mantiene, y git sync hace casi exactamente lo mismo.


Nota: Aunque publiqué mi propia solución, recomendaría el uso de git-up , que también es la respuesta aceptada.

Sé que esta pregunta tiene casi 3 años, pero me hice la misma pregunta y no encontré ninguna solución preparada. Entonces, creé un script de shell de comando git personalizado yo mismo.

Aquí va, el git-ffwd-update hace lo siguiente ...

  1. emite una git remote update para obtener las revoluciones de lates
  2. luego usa git remote show para obtener una lista de sucursales locales que rastrean una sucursal remota (por ejemplo, sucursales que se pueden usar con git pull )
  3. luego verifica con git rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH> la cantidad de confirmaciones que la sucursal local está detrás del control remoto (y viceversa)
  4. Si la sucursal local tiene 1 o más confirmaciones por adelantado, NO puede ser reenviada y necesita ser fusionada o rediseñada a mano.
  5. si la rama local tiene 0 confirmaciones por delante y 1 o más confirmaciones por detrás, git branch -l -f <LOCAL_BRANCH> -t <REMOTE_BRANCH>

El script se puede llamar como:

$ git ffwd-update Fetching origin branch bigcouch was 10 commit(s) behind of origin/bigcouch. reseting local branch to remote branch develop was 3 commit(s) behind of origin/develop. reseting local branch to remote branch master is 6 commit(s) behind and 1 commit(s) ahead of origin/master. could not be fast-forwarded

El script completo, debe guardarse como git-ffwd-update y debe estar en el PATH .

#!/bin/bash main() { REMOTES="$@"; if [ -z "$REMOTES" ]; then REMOTES=$(git remote); fi REMOTES=$(echo "$REMOTES" | xargs -n1 echo) CLB=$(git branch -l|awk ''/^/*/{print $2}''); echo "$REMOTES" | while read REMOTE; do git remote update $REMOTE git remote show $REMOTE -n / | awk ''/merges with remote/{print $5" "$1}'' / | while read line; do RB=$(echo "$line"|cut -f1 -d" "); ARB="refs/remotes/$REMOTE/$RB"; LB=$(echo "$line"|cut -f2 -d" "); ALB="refs/heads/$LB"; NBEHIND=$(( $(git rev-list --count $ALB..$ARB 2>/dev/null) +0)); NAHEAD=$(( $(git rev-list --count $ARB..$ALB 2>/dev/null) +0)); if [ "$NBEHIND" -gt 0 ]; then if [ "$NAHEAD" -gt 0 ]; then echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $REMOTE/$RB. could not be fast-forwarded"; elif [ "$LB" = "$CLB" ]; then echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. fast-forward merge"; git merge -q $ARB; else echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. reseting local branch to remote"; git branch -l -f $LB -t $ARB >/dev/null; fi fi done done } main $@


A partir de git 2.9:

git pull --rebase --autostash

Ver https://git-scm.com/docs/git-rebase

Cree automáticamente un alijo temporal antes de que comience la operación y aplíquelo después de que finalice la operación. Esto significa que puede ejecutar rebase en un área de trabajo sucia. Sin embargo, úselo con cuidado: la aplicación de alijo final después de una reconfiguración exitosa podría resultar en conflictos no triviales.


Se puede hacer usando el siguiente script ... Primero buscará todas las ramas y el proceso de pago uno por uno y se actualizará por sí mismo.

#!/bin/bash git branch -r | grep -v ''/->'' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done set -x CURRENT=`git rev-parse --abbrev-ref HEAD` git fetch --all branch_name=$(git branch | awk ''{print $1" "}'' | grep -v ''*'' | xargs) for branch in $branch_name; do git checkout "$branch" || exit 1 git rebase "origin/$branch" || exit 1 git pull origin $branch|| exit 1 done git checkout "$CURRENT" || exit 1 git pull || exit 1