¿Cómo ver qué commits en una rama no están en la otra?

180

Tengo dos ramas devely next. En desarrollo tengo una cantidad más o menos enorme de commits. Algunos de los commits son seleccionados next. También agregué algunas confirmaciones a la siguiente que se fusionaron devel.

Ahora me gustaría ver lo que falta next, para poder probar los cambios en detalle antes de llevarlos a cabo next. Mi pregunta ahora es, ¿cómo puedo ver en qué commits hay develpero no en el próximo?

Sascha Effert
fuente
su título es un poco engañoso, ya que lo que desea comparar es la punta de ambas ramas. y vine aquí buscando una solución para comparar dos confirmaciones específicas (diferentes) de dos ramas
thebugfinder
¿Duplicar ?: stackoverflow.com/questions/1710894/…
reinierpost

Respuestas:

210

El comando poco utilizado le git cherrymuestra los commits que aún no han sido seleccionados. La documentación para git cherryestá aquí , pero, en resumen, debería poder hacer:

git checkout devel
git cherry next

... y ver la salida un poco como esto:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

Los commits que comiencen +serán los que aún no has elegido next. En este caso, solo había elegido una confirmación hasta el momento. Es posible que desee agregar el -vparámetro al git cherrycomando, para que también muestre la línea de asunto de cada confirmación.

Mark Longair
fuente
Genial, esto es lo que necesitaba. También sería bueno obtener una breve descripción de las pruebas, pero puedo escribir esto.
Sascha Effert
29
No es necesario git checkout devel, solo puedes hacerlo git cherry next devel.
Robin Winslow
21
"Podría querer agregar el -v" ? La cereza sin un -ves como lssin un -la. ; -J
Slipp D. Thompson
1
Y no sabría una manera cherryde marcar o excluir confirmaciones equivalentes, ¿verdad? cherryparece un comando de plomería, pero no (parece) ofrecer muchas opciones. Por lo que estoy actualmente en el medio, git cherryme da falsos positivos, pero @ sehe git log --cherry-pickexcluye correctamente los commits previamente seleccionados / rebajados.
Slipp D. Thompson
La documentación proporciona un ejemplo concreto: git-scm.com/docs/git-cherry#_concrete_example
enms.
107

Además, puedes usar

git log --left-right --graph --cherry-pick --oneline devel...next

para obtener una buena lista de confirmaciones diferentes reales no compartidas entre las ramas.

La palabra operativa es --cherry-pick

--cherry-pick

Omita cualquier confirmación que introduzca el mismo cambio que otra confirmación en el "otro lado" cuando el conjunto de confirmaciones está limitado con una diferencia simétrica. Por ejemplo, si tiene dos ramas, A y B, una forma habitual de enumerar todas las confirmaciones en un solo lado de ellas es con --izquierda-derecha, como el ejemplo anterior en la descripción de esa opción. Sin embargo, muestra los commits que fueron seleccionados de la otra rama (por ejemplo, "3rd on b" puede ser seleccionado de la rama A). Con esta opción, dichos pares de confirmaciones se excluyen de la salida.

Actualización Como se menciona en un comentario, se agregaron versiones recientes de git --cherry-mark:

--cherry-mark

Como --cherry-pick (ver más abajo) pero marca las confirmaciones equivalentes con = en lugar de omitirlas, y las no equivalentes con +.

sehe
fuente
1
Esto no funcionó para mí. Mi versión de git no sabe: una línea, por lo tanto, la eliminé. Luego tuve que intercambiar desarrollo y luego y funcionó. ¡Muy agradable!
Sascha Effert
@SaschaEffert: no tuvo que cambiar el desarrollo y el siguiente (observe TRES puntos, no DOS). Dicho esto, las cosas pueden ser diferentes si usas una versión antigua de git (?) Pero en ese caso deberías haber obtenido un error de análisis en los tres puntos.
sehe
2
Por diversión, me di cuenta de que la sintaxis rev-parse '...' (diferencia simétrica) se agregó en julio de 2006 , y la documentación se actualizó en junio de 2008 . ¡La alegría del código abierto!
sehe
1
'gls --primero padre --cherry-mark --desarrollo solo a la izquierda ... siguiente' donde gls es mi alias de registro git con todo el formato bonito. cherry-mark muestra los commits seleccionados y no seleccionados en el desarrollo, pero los marca de manera diferente.
angularsen
1
agregar --no-fusiones tal vez mejor
MervynYang
51

Podría intentar hacer subconjuntos de registro git:

git log --oneline devel ^next
Bryan Buckley
fuente
44
En mi opinión, esta es la mejor solución (la respuesta de @sehe también muestra los compromisos en el siguiente que no están en desarrollo, en el contexto del OP, no hay ninguno, pero en el mío sí, el uso --left-onlyhubiera sido mejor). Sin embargo, este se puede mejorar un poco agregando --no-mergespara omitir cualquier confirmación de fusión (por ejemplo, si una característica o rama de revisión se fusionó (por separado) en desarrollo y siguiente). Hablando estrictamente, por supuesto, la resolución de conflictos en las fusiones puede crear otras diferencias, pero ese no suele ser el caso. La --no-mergesopción se puede aplicar útilmente a las otras respuestas también.
Alex Dupuy
27

Qué tal si

git log next..devel

El resultado es similar a la respuesta de Byran (diferente orden de confirmaciones) pero ambas respuestas producirán confirmaciones que son diferentes entre las ramas, en lugar de mostrar lo que hay en una rama y no en la otra.

justingordon
fuente
44
También puede omitir la segunda rama si actualmente está en esa rama. es decirgit log next..
jmaxyz
por cierto 'git log next..devel' es diferente de 'git log devel..next'
Eugene Kaurov el
1

Para obtener la lista de confirmaciones que no se integraron en la rama de lanzamiento (siguiente), puede usar:

git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt

Consulte git-rev-list para obtener más información.

Mihai
fuente
Al comando de esta respuesta le faltan las ramas reales en cuestión, es decirnext...devel
Alex Dupuy
@AlexDupuy Yah, es una respuesta bastante tonta. Dado que tampoco es la respuesta más simple y no explica por qué este enfoque sería mejor, estoy -1 -ing ella.
Slipp D. Thompson
-1

@Mark Longair lo logró en su respuesta aquí , pero me gustaría agregar una idea adicional.

Relacionado y respondiendo a la pregunta de cómo dividir una solicitud de extracción (PR) grande, especialmente cuando aplastar sus confirmaciones no es práctico debido a una o más fusiones de master en su feature_branch

Mi situación:
hice una gran apuesta feature_branchcon 30 confirmaciones y abrí una solicitud de extracción (PR) en GitHub para fusionarla master. Branch mastercambió una tonelada debajo de mí y recibió 200 confirmaciones feature_branchque no tenía. Para resolver conflictos que hice git checkout feature_branchy git merge masterpara fusionar masterlos cambios en mi feature_branch. Elegí en mergelugar del rebaseúltimo maestro, por lo que tendría que resolver los conflictos solo una vez en lugar de potencialmente 30 veces (una vez para cada una de mis confirmaciones). No quería aplastar mis 30 commits en 1 primero y luego rebase en el últimomasterporque eso podría borrar el historial de comentarios de revisión de GitHub en el PR. Entonces, fusioné master en mi rama de características y resolví conflictos 1 sola vez. Todo estuvo bien. Sin embargo, mi RP era demasiado grande para que mis colegas la revisaran. Necesitaba dividirlo. Fui a aplastar mis 30 commits y ¡OH NO! ¿DÓNDE ESTÁN? ¡TODOS ESTÁN INTERMITADOS CON masterlas 200 confirmaciones recientes ahora porque me fusioné con mastermi feature_branch! ¿QUÉ DEBO HACER?

git cherryuso en caso de que quiera intentar git cherry-pickconfirmaciones individuales:

git cherry al rescate (más o menos)!

Para ver todos los commits que están dentro feature_branchpero NO dentro master, puedo hacer:

git checkout feature_branch
git cherry master

O bien, puedo verificar las confirmaciones de CUALQUIER rama sin asegurarme de que estoy en feature_branchprimer lugar haciendo git cherry [upstream_branch] [feature_branch]esto. Nuevamente, esto verifica qué confirmaciones ESTÁN en feature_branchpero NO en upstream_branch( masteren este caso):

git cherry master feature_branch

Agregar -vtambién muestra las líneas de asunto del mensaje de confirmación:

git cherry -v master

La canalización a "recuento de palabras", "líneas" ( wc -l) cuenta cuántas confirmaciones hay:

git cherry master | wc -l

Puede comparar este recuento con el número de confirmación que se muestra en su GithHub PR para sentirse mejor al saber que git cherryrealmente está funcionando. También puede comparar los hash de git uno por uno y ver si coinciden con git cherryGitHub. Tenga en cuenta que git cherryno contará ningún commit de combinación en la que fueron fusionados masteren feature_branch, pero GitHub VOLUNTAD. Entonces, si ve una pequeña discrepancia en el recuento, busque en la página de confirmación de relaciones públicas de GitHub la palabra "fusionar" y probablemente verá que ese es el culpable que no aparece git cherry. Por ejemplo: una confirmación titulada "Combinar rama 'maestro' en feature_branch" aparecerá en el PR de GitHub, pero no cuando se ejecute git cherry master feature_branch. Esto está bien y se espera.

Entonces, ahora tengo un medio para descubrir qué diferencias me gustaría elegir en una nueva rama de características para dividir esta diferencia: puedo usar git cherry master feature_branchlocalmente o mirar los commits en el PR de GitHub.

Cómo podría ayudar el aplastamiento, si tan solo pudiéramos aplastarlo:

Sin embargo, una alternativa para dividir mi gran diferencia es aplastar mis 30 confirmaciones en una sola, aplicar un parche en una nueva rama de características, restablecer de forma parcial la confirmación de la revisión, luego usar git guipara agregar piezas archivo por archivo, fragmento por fragmento o linea por linea. Una vez que obtengo una subfunción, puedo confirmar lo que he agregado y luego revisar una nueva rama, agregar un poco más, confirmar, revisar una nueva rama, etc., hasta que tenga mi gran característica dividida en varias subfunciones . El problema es que mis 30 commits se entremezclan con los otros 200 commits de otras personas debido a mi git merge masteren mi feature_branch, por lo que rebase no es práctico, ya que tendría que seleccionar 230 commits para reordenar y aplastar mis 30 commits.

Cómo usar un archivo de parche como un reemplazo mucho más fácil para aplastar:

Una solución alternativa es simplemente obtener un archivo de parche que contenga un "equivalente de squash" de mis 30 confirmaciones, parchearlo en una nueva bifurcación de master(una nueva rama de subfunción) y trabajar desde allí, de la siguiente manera:

git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master 
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch

Ahora tengo mi parche de 30 confirmaciones todo aplicado localmente, pero sin etapas y sin compromiso.

Ahora use git guipara agregar archivos, fragmentos y / o líneas y dividir su gran PR o "diff":

Tenga en cuenta que si no tiene git gui, puede instalarlo fácilmente en Ubuntu con sudo apt install git-gui.

Ahora puedo ejecutar git guiy comenzar a agregar archivos, fragmentos y / o líneas (haciendo clic con el botón derecho en el programa git GUI), y dividir la rama de la función de confirmación 30 en sub ramas como se describe arriba, agregando, confirmando y bifurcando repetidamente una nueva rama de funciones y repetir este ciclo hasta que todos los cambios se hayan agregado a una rama secundaria y mi función de confirmación 30 se divida con éxito en 3 o 4 subcaracterísticas. Ahora puedo abrir un RP por separado para cada una de estas subfunciones, y será más fácil para mi equipo revisarlas.

Referencias

  1. Cree un parche o un archivo diff desde el repositorio git y aplíquelo a otro repositorio git diferente
Gabriel Staples
fuente
Necesitaba hacer referencia a esta respuesta hoy, pero no pude encontrarla rápidamente. Afortunadamente, tenía un voto negativo para ayudarme a encontrarlo más fácilmente, por lo que un simple clic en el icono de la copa de premios en la parte superior derecha de la pantalla mostró dónde recientemente perdí 2 puntos, y al hacer clic en eso me trajo de vuelta aquí donde puedo ahora referencia mi propia respuesta aquí! Espero no recibir más votos negativos, pero para el votante negativo, ¡gracias por el servicio que accidentalmente me ayudó!
Gabriel Staples