Usando Git, muestre todas las confirmaciones que están en una rama, pero no en la (s) otra (s)

465

Tengo una rama vieja, que me gustaría eliminar. Sin embargo, antes de hacerlo, quiero comprobar que todas las confirmaciones realizadas en esta rama se fusionaron en algún otro punto. Por lo tanto, me gustaría ver todas las confirmaciones realizadas en mi rama actual que no se hayan aplicado a ninguna otra rama [o, si esto no es posible sin alguna secuencia de comandos, ¿cómo se ven todas las confirmaciones en una rama que no se han aplicado? a otra rama dada?].

sircolinton
fuente
Para enumerar confirmaciones faltantes entre dos ramas, puede usar compare-branches.py bitbucket.org/aakef/compare-git-branches
Bernd Schubert
Relacionado: stackoverflow.com/q/1419623/1959808
Ioannis Filippidis

Respuestas:

321

Probablemente solo quieras

git branch --contains branch-to-delete

Esto mostrará una lista de todas las ramas que contienen los commits de "branch-to-delete". Si informa más que solo "rama a borrar", la rama se ha fusionado.

Sus alternativas son realmente cosas de sintaxis de lista de revoluciones. Por ejemplo, git log one-branch..another-branchmuestra todo lo que one-branchnecesita tener todo lo que another-branchtiene.

También te puede interesar git show-branchcomo una forma de ver qué es dónde.

Dustin
fuente
2
+1. Ver también stackoverflow.com/questions/850607/…
VonC
1
La línea 'Si se informa de algo, la rama ha fusionado' puede ser mal interpretado: si git branch --contains some-branchsólo vuelve some-branch, entonces se hace el retorno algo, pero ha no han fusionado.
Confusión
55
Tenga en cuenta que git log foo..barmostrará las confirmaciones entre la última barra y la última de foo, pero no faltan otras confirmaciones de más atrás en el tiempo. Para ver todo en bar pero no en foo, debes usar la solución de @ jimmyorr.
Paul A Jungwirth
557

Para ver una lista de las confirmaciones que están en una rama pero no en otra, use git log:

git log --no-merges oldbranch ^newbranch

... es decir, mostrar registros de confirmación para todas las confirmaciones en oldbranch que no están en newbranch. Puede enumerar varias ramas para incluir y excluir, p. Ej.

git log  --no-merges oldbranch1 oldbranch2 ^newbranch1 ^newbranch2

Nota: en Windows ^es una tecla de escape, por lo que debe escaparse con otra ^:

git log --no-merges oldbranch ^^newbranch
jimmyorr
fuente
2
Lo encontré buscando git compare commits de dos ramas.
Usuario
25
Esto es exactamente lo que estaba buscando. Pero, usarlo ^como prefijo aquí me confundió. En este contexto, significa excluir esa rama. Usar ^como sufijo sería una referencia relativa a la confirmación principal de esa rama.
Joe Flynn
44
Muy útil gracias. Tengo curiosidad, ¿por qué es necesaria la bandera --no-merges? ¿Seguramente uno quiere ver esos commits también?
Max MacLeod
2
¿Te gustaría usar gitk con esto? Simplemente use gitk oldbranch ^newbranch --no-merges(Probado con git 1.8.1.1). Nota al margen, para mí ^significa compromiso HEAD inclusivo de rama newbranch.
Matt
2
@NazariiGudzovatyi: sí, hay: "-cherry-pick". Hay una ENORME cantidad de opciones para iniciar sesión en la página de documentación
romeara
91

Para mostrar los commits en oldbranch pero no en newbranch:

git log newbranch..oldbranch

Para mostrar la diferencia por estas confirmaciones (tenga en cuenta que hay tres puntos):

git diff newbranch...oldbranch

Aquí está el documento con una ilustración del diagrama https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#Commit-Ranges

Xuan
fuente
Ver el comentario de Paul A Jungwirth arriba. ¿Parece que esto se perderá algunos compromisos antiguos?
Variable miserable el
2
No estoy seguro de lo que significan los viejos compromisos. Los puntos dobles básicamente le piden a Git que resuelva un rango de confirmaciones que son accesibles desde una confirmación pero no son accesibles desde otra. Aquí está el documento con una ilustración digram git-scm.com/book/en/v2/…
Xuan
1
y si tenemos en cualquiera newbrancho oldbranch, podemos hacer git log ..oldbrancho git log newbranch..respectivamente
YakovL
La solución de jimmyorr no funcionó para mí, pero esta lo hizo gracias a los dos puntos ..entre los nombres de los árbitros. También utilicé la --cherry-pickopción para ocultar las confirmaciones que están presentes en ambas ramas pero que tienen un hash diferente porque se seleccionaron de una rama a otra.
flawyte
58

Para aquellos que todavía buscan una respuesta simple, echa un vistazo a git cherry . Compara las diferencias reales en lugar de los hash de confirmación. Eso significa que tiene en cuenta los compromisos que se han seleccionado o rebajado.

Primero revise la rama que desea eliminar:

git checkout [branch-to-delete]

luego use git cherry para compararlo con su rama de desarrollo principal:

git cherry -v master

Salida de ejemplo:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message
- 85867e38712de930864c5edb7856342e1358b2a0 Yet another message

Nota: El -vindicador debe incluir el mensaje de confirmación junto con el hash SHA.

Las líneas con el '+' al frente están en la rama para borrar, pero no en la rama maestra. Aquellos con un '-' en frente tienen un commit equivalente en master.

Para SOLO los commits que no están en master, combine cherry pick con grep:

git cherry -v master | grep "^\+"

Salida de ejemplo:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message
Tim S
fuente
He intentado esto, pero aún informa que hay muchos commits en fb (rama de características) que no están en mb (rama principal). Sin embargo, si estoy en el fb y hago un git diff mb, no veo diferencias. Usé rebase y aplasté todo. Estoy casi seguro de que es por eso, pero solo quiero estar seguro. Si este es el caso, entonces evitaré aplastar si es posible; Estoy en el "campo de información sin pérdida". Me pregunto si sería posible agregar un modo de visualización de registro que pueda mostrar fusiones como si fueran rebases para mantener el historial limpio y sin perder información.
Outis Von Nemo
1
No estoy seguro de su escenario exacto aquí, pero si ha agrupado varias confirmaciones en una sola y está comparando eso con otra rama donde las confirmaciones están separadas, esto definitivamente no funcionará. En ese caso, es posible que solo desee utilizar la diffutilidad Unix para comparar los distintos archivos. O bien, podría crear una rama temporal y aplastar todas las confirmaciones de manera similar a lo que hizo con la rama original, y luego usar esto, que creo que funcionaría.
Tim S
50

Si bien algunas de las respuestas publicadas aquí ayudarán a encontrar lo que busca, el siguiente subcomando de git branch es una solución más adecuada para su tarea.

--merged se usa para encontrar todas las ramas que se pueden eliminar de forma segura, ya que esas ramas están completamente contenidas por HEAD.

Mientras que en masteruno se podía ejecutar el comando para enumerar las ramas que se podían eliminar de forma segura, así:

git branch --merged
  develop
  fpg_download_links
* master
  master_merge_static

# Delete local and remote tracking branches you don't want
git branch -d fpg_download_links
git push origin :fpg_download_links
git branch -d master_merge_static
git push origin :master_merge_static

# There is also a flag to specify remote branches in the output
git branch --remotes --merged
Freddie
fuente
16

La respuesta de jimmyorr no funciona en Windows. ayuda a usar en --notlugar de hacerlo ^así:

git log oldbranch --not newbranch --no-merges
sebeck
fuente
44
Eso es correcto, +1. Nota sin embargo que ^es compatible con Windows, pero tiene que ser escapado, lo que, en Windows, es (otro) ^: git log oldbranch ^^newbranch --no-merges.
VonC
3
Para ser específicos, funciona en Windows en la consola Powershell, pero requiere "^" adicional en CMD.
Rod
7

Si es una rama (única) que necesita verificar, por ejemplo, si desea que la rama 'B' esté completamente fusionada con la rama 'A', simplemente puede hacer lo siguiente:

$ git checkout A
$ git branch -d B

git branch -d <branchname> tiene la seguridad de que "La rama debe estar completamente fusionada en HEAD".

Precaución : esto realmente elimina la rama B si se fusiona con A.

Jakub Narębski
fuente
3

Puede usar este script simple para ver confirmaciones que no se fusionan

#!/bin/bash
# Show commits that exists only on branch and not in current
# Usage:
#   git branch-notmerge <branchname>
#
# Setup git alias
#   git config alias.branch-notmerge [path/to/this/script]
grep -Fvf <(git log --pretty=format:'%H - %s') <(git log $1 --pretty=format:'%H - %s')

También puede usar la herramienta git-wtf que mostrará el estado de las ramas

manRo
fuente
0

Solo use git cherrypara elegir todas las confirmaciones en la rama, newFeature42por ejemplo:

git cherry -v master nuevo

Mꜳltus
fuente
-5

Comience a crear una solicitud de extracción a través del servicio de alojamiento git que está utilizando. Si la rama se ha fusionado completamente con la rama base, no podrá crear el nuevo RP.

En realidad, no necesita hacer la solicitud de extracción, solo use el primer paso donde elija las ramas.

Por ejemplo, en GitHub:

No hay nada para comparar

No se puede crear un RP para las ramas que se han fusionado.

Esto no usa git en la línea de comando, pero a menudo encuentro útil usar las otras herramientas a su disposición con un modelo mental claro en lugar de intentar recordar otro comando aritano de git.

pkamb
fuente