Usando Git, ¿cómo encuentro cambios entre local y remoto?


152

Aquí hay dos preguntas diferentes, pero creo que están relacionadas.

  1. Cuando uso Git, ¿cómo encuentro qué cambios he comprometido localmente, pero aún no he enviado a una sucursal remota? Estoy buscando algo similar al comando Mercurial hg outgoing.

  2. Cuando uso Git, ¿cómo encuentro qué cambios tiene una rama remota antes de hacer un pull? Estoy buscando algo similar al comando Mercurial hg incoming.

Para el segundo: ¿hay alguna forma de ver lo que está disponible y luego elegir los cambios que quiero obtener?


11
Al mirar las respuestas, parece haber cierta confusión sobre qué hg incomingy qué hg outgoinghacer realmente. El equivalente de Git más cercano que encontré es la --dry-runopción. Justo git pull --dry-runy verás una lista de todas las cosas que deben suceder.
Roman Starkov

Respuestas:


97

Git no puede enviar ese tipo de información a través de la red, como puede hacer Hg. Pero puede ejecutar git fetch(que es más parecido hg pulla hg fetch) para obtener nuevas confirmaciones de sus servidores remotos.

Entonces, si tiene una rama llamada mastery una remota llamada origin, después de ejecutar git fetch, también debe tener una rama llamada origin/master. A continuación, puede obtener git logtodos los commits que masterdeben ser un superconjunto origin/masteral hacer git log master..origin/master. Invierta esos dos para obtener lo contrario.

Un amigo mío, David Dollar, ha creado un par de scripts de git shell para simular hg incoming/outgoing. Puede encontrarlos en http://github.com/ddollar/git-utils .


113

Comenzando con Git 1.7.0, hay una sintaxis especial que le permite referirse genéricamente a la rama ascendente: @{u}o @{upstream}.

Para imitar hg incoming:

git log ..@{u}

Para imitar hg outgoing:

git log @{u}..

Uso lo siguiente incomingy los outgoingalias para hacer que lo anterior sea más fácil de usar:

git config --global alias.incoming '!git remote update -p; git log ..@{u}'
git config --global alias.outgoing 'log @{u}..'

git log .. @ {u} me da estos errores. (Tengo tanto el origen como un repositorio ascendente en mi configuración de git). error: no se encontró una rama ascendente para '' error: no se encontró una rama ascendente para '..' error: no se encontró una rama ascendente para '..' fatal: argumento ambiguo '.. @ {u}': revisión desconocida o ruta no en El árbol de trabajo. Use '-' para separar las rutas de las revisiones
Henrik

66
Obtendrá esos errores si su sucursal local no está configurada con un flujo ascendente. Para arreglarlo, corre git branch --set-upstream foo origin/foo.
Richard Hansen el

git log @{u}..enumera cada cambio en el repositorio para mí. No hay forma de que aún no existan.
Roman Starkov

@romkyns: es posible que su sucursal local tenga la sucursal remota incorrecta configurada como ascendente. Asegúrese de git rev-parse --symbolic-full-name @{u}imprimir la referencia remota adecuada. Además, git log @{u}..muestra las confirmaciones a las que la rama ascendente no puede acceder, que pueden incluir confirmaciones que ya están en el repositorio remoto (si se puede acceder a ellas mediante una referencia diferente). Esto sucederá justo después de fusionarse en una rama ya empujada.
Richard Hansen

@RichardHansen Me temo que soy demasiado novato para saber qué sería apropiado para una referencia remota, sin embargo, este fue un repositorio recién clonado en el que hice solo un checkout <somebranch>y merge <otherbranch>. En este punto, hice el log @{u}..y vi todos los cambios enumerados.
Roman Starkov

42

No es una respuesta completa, pero git fetch extraerá el repositorio remoto y no hará una fusión. Entonces puedes hacer un

git diff maestro origen / maestro


1
Trabajó para mí (pero al revés) -git diff origin/master master
Nick Grealy

34
  1. Use "git log origin..HEAD"

  2. Utilice "git fetch" seguido de "git log HEAD..origin". Puede seleccionar confirmaciones individuales utilizando los ID de confirmación enumerados.

Lo anterior supone, por supuesto, que "origen" es el nombre de su rama de seguimiento remoto (que es si ha utilizado clonar con opciones predeterminadas).


3
(Y si no está rastreando la rama remota, es "git log origin / master..HEAD".)
plindberg

44
"origen" no es el nombre de la rama de seguimiento remoto, es el nombre del control remoto. Y solo especificar el nombre remoto no funciona, debe especificar la rama de seguimiento remoto, que sería origen / maestro.
robinst

22

También hay esto, para comparar todas las ramas:

git log --branches --not --remotes=origin

Esto es lo que dice la página de manual de git log sobre esto:

Muestra todas las confirmaciones que se encuentran en cualquiera de las sucursales locales pero no en ninguna de las sucursales de seguimiento remoto para el origen (lo que tiene ese origen no).

Lo anterior es para outgoing. Para incoming, simplemente intercambiar:

git log --remotes=origin --not --branches

8

yo lo haría

$ git fetch --dry-run

para hg incomingy

$ git push --dry-run

para hg outgoing.


Lo siento, pasé por alto que esto ya se dijo como un comentario al OP.
Chris

1

git-out es un script que emula con hg outgoingbastante precisión. Se analiza en la salida "push -n", por lo que produce una salida precisa si necesita especificar argumentos adicionales para empujar.


0

git entrante

$ git fetch && git log ..origin/master --stat
OR
$ git fetch && git log ..origin/master --patch

git saliente

$ git fetch && git log origin/master.. --stat
OR
$ git fetch && git log origin/master.. --patch

0

Cuando las respuestas "git log" y @ {u} inicialmente me dieron errores de "revisión desconocida", probé la sugerencia de Chris / romkyns de git push --dry-run.

Obtendrá una salida como "5905..4878 master-> master". 5905 es la última confirmación que tiene el control remoto y los compromisos a través de (e incluyendo) 4878 se aplicarán al control remoto.

Luego puede usar 5905..4878 como argumentos para varios otros comandos git para obtener más detalles:

git diff 5905..4878 # Gives full code changes in diff style

git log --online 5905..4878 # Displays each commit's comment

-1

Cuando hace git fetch, todo el contenido, incluidas las ramas, las etiquetas (referencias) se almacenan temporalmente en .git / FETCH_HEAD cuyo contenido se puede ver con el comando: git log FETCH_HEAD Si no usa el sufijo -a con git fetch, entonces de manera predeterminada , El contenido de FETCH_HEAD se sobrescribirá con nuevos contenidos. A partir de estos contenidos, puede ver y decidir a qué rama desea fusionarlos si lo hace, o puede elegir simplemente si desea solo unas pocas confirmaciones de lo que se ha traído por fetch.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.