Git pull da como resultado mensajes extraños de "Merge branch" en el registro de confirmación

110

Estoy trabajando con otro desarrollador en un proyecto y estamos usando Github como nuestro repositorio remoto. Estoy en una Mac usando git 1.7.7.3, él en Windows usando git 1.7.6.

Esto es lo que esta pasando

  1. Uno de nosotros (llamémosle desarrollador A, pero no importa cuál) envía un conjunto de confirmaciones a GitHub.
  2. El otro (desarrollador B) realiza algunas confirmaciones locales.
  3. B hace a git pull.
  4. B hace a git push.
  5. Mirando el registro del historial de confirmaciones, veo Merge branch 'master' de github.com:foo/bar

El registro de confirmación se llena de mensajes de "Fusionar rama" a lo largo del tiempo, y también muestra al desarrollador B confirmando los cambios que realizó el desarrollador A. La única forma que hemos encontrado para prevenir este problema ha sido hacer un git pull --rebasepaso 3, pero no sé qué efectos secundarios introducirá el rebase. Esta es la primera vez que trabajo en un repositorio de git de múltiples desarrolladores, ¿es este un comportamiento normal? ¿Alguna idea sobre cómo resolver este problema?

mshafrir
fuente
2
Puede ver el registro sin fusiones congit log --no-merges
wjandrea

Respuestas:

88

El compromiso que está viendo está perfectamente bien. A se pullejecuta de manera efectiva git fetchy, git mergepor lo tanto, generalmente se produce una fusión cuando se ejecuta git pull.

La alternativa de utilizar rebase en lugar de fusionar es posible, pero normalmente debería evitarlo. Rebasar le permite mantener un historial lineal, pero también elimina cualquier información sobre la ramificación que ocurrió originalmente. También hará que se reescriba el historial de la rama actual, recreando todas las confirmaciones que no están contenidas en la rama de destino (en su caso, la remota). Como las confirmaciones recreadas son confirmaciones diferentes , esto puede causar mucha confusión cuando se desarrolla junto con otros, especialmente cuando las personas ya revisaron partes de esas confirmaciones antes de que se reescriban (por ejemplo, con ramas de características). Por lo tanto, como regla general, nunca debe volver a escribir ningún compromiso que ya haya sido enviado.

Las confirmaciones que ves están ahí para combinar dos (o más) ramas. Está perfectamente bien tener una confirmación que no haga nada más que fusionar varias ramas. De hecho, lo deja muy claro cuando tiene un compromiso de fusión que combina ramas al mirar el historial. En comparación con el rebase, la fusión también le permite ver efectivamente el historial original a medida que se desarrolló, incluidas las ramas reales que coexistieron.

Entonces, en pocas palabras: sí, tener confirmaciones de fusión está perfectamente bien y no debe preocuparse por ellas.

dar un toque
fuente
2
Muy buena respuesta. Yo mismo probé el estilo rebase ya que se recomendaba en algunas pautas de contribución de proyectos de código abierto y me causaba problemas. Un nuevo miembro del equipo también tuvo lo mismo. Creo que la opción de rebase no es para equipos que trabajen juntos todo el día, pero es correcta para proyectos que tienen contribuyentes principales y otros contribuyentes que solo envían parches. Deben estar bien obteniendo el repositorio principal y reajustando sus cambios justo antes de emitir una solicitud de extracción.
Meligy
2
@sTodorov Si no hay cambios nuevos, entonces la parte de recuperación de la extracción no hará nada, pero la fusión aún se está ejecutando. Entonces, si su sucursal local actual no está actualizada, fusionará los nuevos cambios en su sucursal. Y si no puede hacer una combinación de avance rápido (si tiene confirmaciones divergentes), creará una combinación de confirmación.
empuje el
28
Esta respuesta hace que parezca que usar rebase como lo ha descrito el OP es peligroso, pero no lo es. Rebasar en el paso 3 no reescribe todo el historial. Solo las confirmaciones locales que no se han enviado se reescriben volviéndose a aplicar encima del nuevo HEAD (la última confirmación enviada a esa rama). Esto evita las confirmaciones de fusión extrañas y no tiene otros efectos secundarios.
bob esponja
1
@bobesponja Se reescriben todas las confirmaciones que no están en la rama remota extraída. Esto puede incluir confirmaciones publicadas de otras ramas, por ejemplo, con ramas de funciones, a las que otros pueden haber accedido antes. Como tal, sí, rebasar sin pensar en lo que rebase es algo peligroso.
empuje el
1
@bobesponja Sí, si está publicando su rama de características antes (porque otros trabajan en ella, o simplemente como copia de seguridad), entonces no debe volver a basarla porque otros ya podrían haberla obtenido. Rebasar entonces, como usted mismo dice, va en contra de las pautas de rebase que establecí en mi respuesta. Sin embargo, si no publica sus confirmaciones, la reorganización está bien si lo desea y no le importa el historial lineal. Pero depende de cómo trabajes, por lo que la respuesta general es evitarlo a menos que sea realmente seguro. Por cierto. Revisé mi respuesta, así que si el problema se resuelve, le agradecería que eliminara su voto negativo.
empuje el
48

Esta respuesta ha sido revisada, ya que mi comprensión, diagramas y conclusiones eran incorrectos.


git pullprovoca que la fusión se confirme porque git se está fusionando. Esto se puede cambiar configurando sus ramas para usar rebase en lugar de fusionar. El uso de rebase en lugar de fusionar en una extracción proporciona un historial más lineal al repositorio compartido. Por otro lado, las confirmaciones de fusión muestran los esfuerzos de desarrollo paralelos en la rama.

Por ejemplo, dos personas están trabajando en la misma rama. La rama comienza como:

...->C1

La primera persona termina su trabajo y empuja hacia la rama:

...->C1->C2

La segunda persona termina su trabajo y quiere presionar, pero no puede porque necesita actualizar. El repositorio local para la segunda persona se ve así:

...->C1->C3

Si la extracción está configurada para fusionarse, el repositorio de la segunda persona se verá así.

...->C1->C3->M1
      \      /
       ->C2->

Donde M1 es un compromiso de fusión. Este nuevo historial de sucursales se enviará al repositorio. Si, en cambio, la extracción está configurada para volver a establecer la base, el repositorio local se vería así:

...->C1->C2->C3

No hay compromiso de fusión. La historia se ha hecho más lineal.

Ambas opciones reflejan la historia de la rama. git te permite elegir qué historial prefieres.

De hecho, hay lugares donde la rebase puede causar un problema con las sucursales remotas. Este no es uno de esos casos. Preferimos usar rebase, ya que simplifica un historial de rama ya complicado y muestra una versión del historial relativa al repositorio compartido.

Puede configurar branch.autosetuprebase = always para que git establezca automáticamente sus ramas remotas como rebase en lugar de master.

git config --global branch.autosetuprebase always

Esta configuración hace que git cree automáticamente una configuración para cada rama remota:

branch.<branchname>.rebase=true

Puede configurarlo usted mismo para sus sucursales remotas que ya están configuradas.

git config branch.<branchname>.rebase true

Me gustaría agradecer a @LaurensHolst por cuestionar y seguir mis declaraciones anteriores. Ciertamente he aprendido más sobre cómo funciona git con las confirmaciones de extracción y fusión.

Para obtener más información sobre las confirmaciones de fusión, puede leer Contribuir a un proyecto en ProGit-Book . La sección Private Small Team muestra las confirmaciones de fusión.

Bill puerta
fuente
7
“El uso de rebase en lugar de fusionar en una extracción proporciona el historial correcto al repositorio compartido. El uso de la combinación proporciona un historial falso ". - ¿Cuál es el fundamento que respalda esta afirmación tan audaz? No hay forma de que una historia con fusiones sea una 'historia falsa'. Es una descripción precisa del orden en que sucedieron las cosas. Lo que está haciendo al reajustar es alterar el historial para crear una versión un poco más lineal del mismo. Sacrificas la precisión por la estética. Quizás algo que prefieras hacer, pero de ninguna manera más veraz.
Laurens Holst
2
Usar rebase en lugar de fusionar no sacrifica la precisión por la estética. Usamos --no-ff para las fusiones, por lo que la estética no es un requisito. La precisión es un deseo. Rebase proporciona esa precisión.
Bill Door
2
¿Cómo es más precisa la historia rebasada? No aclaras esto, y no veo cómo sería.
Laurens Holst
1
El historial es un reflejo del momento en que se produjeron las confirmaciones en el repositorio compartido . Un día 1, el repositorio compartido vio el compromiso C2. El día 2, el repositorio compartido ve el compromiso C3. Si C3 viniera antes que C2, entonces el reflejo del tiempo no sería correcto. C3 no vino antes que C2. Todo lo que hace esa rebase es reorganizar las confirmaciones en el repositorio local para reflejar correctamente el historial que muestra el repositorio compartido.
Bill Door
6
Sus preguntas me llevaron a revisar mi comprensión de las confirmaciones de fusión. Mi diagrama es incorrecto. Estoy revisando la discusión. Mis conclusiones también son incorrectas. El historial de rebase y merge es igualmente correcto. Puede hacer su propia elección.
Bill Door
11

Tu puedes hacer:

git pull --rebase

Sin embargo, esto siempre pondrá tus cambios por encima de los de tus colaboradores. Pero no recibirá ningún mensaje de fusión contaminante.

gaboroso
fuente
9

En realidad, hay una respuesta mucho más simple a esto. Simplemente haga que el desarrollador B haga un tirón ANTES de realizar su compromiso. Esto evitará las confirmaciones de fusión, ya que son causadas por el historial que ha creado en su repositorio local desde su confirmación local que intenta fusionarse con el historial de confirmaciones en el repositorio remoto. Si recibe un mensaje que dice algo como 'los cambios se sobrescribirán' al hacer una extracción, solo significa que ambos tocaron el mismo archivo, así que hágalo:

git stash
git pull
git stash pop

entonces puede resolver cualquier conflicto de fusión si hay alguno.

Luke
fuente
Lo más molesto y ansioso son exactamente los conflictos de fusión. Prefiero evitarlo
Verde
1
@Green Si está preocupado por los conflictos de fusión, incluso git pull no es diferente.
Zoso
Excepto aquella vez en la que te olvidas stashantes de ti pull. Ugh git requiere que esté en la cima de mi juego todo el tiempo.
linuxNoob
Necesidad de git pull --rebaseintegrar cambios remotos antes que los locales, independientemente.
vonbrand
7

Hacer un git pull insertará los mensajes "Merge branch", eso es exactamente lo que hace. Al hacer un git pull, ha fusionado la rama remota en su rama local.

Cuando haces un git pull y hay conflictos, el registro de git mostrará las actualizaciones de los archivos en conflicto como provenientes del usuario que resolvió los conflictos. Supongo que esto se debe a que la persona que soluciona el conflicto vuelve a confirmar el archivo.

Hasta donde yo sé, así es como funciona git, y no hay forma de evitarlo.

Al volver a basar, se acabará el historial de git, por lo que no podrá ver cuándo se produjeron las fusiones.

kclair
fuente