¿Hay un & # 8220; suyo & # 8221; versión de & # 8220; git merge -s our & # 8221 ;?

StackOverflow https://stackoverflow.com/questions/173919

  •  05-07-2019
  •  | 
  •  

Pregunta

Al fusionar rama de tema " B " en " A " Al usar git merge , obtengo algunos conflictos. Sé que todos los conflictos se pueden resolver utilizando la versión en "B".

Soy consciente de git merge -s our . Pero lo que quiero es algo como git merge -s suyo .

¿Por qué no existe? ¿Cómo puedo lograr el mismo resultado después de la fusión conflictiva con los comandos git existentes? ( git checkout cada archivo no combinado de B)

ACTUALIZACIÓN: La " solución " de descartar cualquier cosa de la rama A (el punto de confirmación de fusión a la versión B del árbol) no es lo que estoy buscando.

¿Fue útil?

Solución

Agregue la opción -X a suyo . Por ejemplo:

git checkout branchA
git merge -X theirs branchB

Todo se fusionará de la manera deseada.

Lo único que he visto que causa problemas es si los archivos se eliminaron de branchB. Se muestran como conflictos si algo más que git hizo la eliminación.

La solución es fácil. Simplemente ejecute git rm con el nombre de los archivos que se eliminaron:

git rm {DELETED-FILE-NAME}

Después de eso, el -X suyo debería funcionar como se esperaba.

Por supuesto, hacer la eliminación real con el comando git rm evitará que el conflicto ocurra en primer lugar.


Nota : también existe una opción de formulario más largo. Para usarlo, reemplace:

-X theirs

con:

--strategy-option=theirs

Otros consejos

Una solución posible y probada para fusionar la rama B en nuestra rama A extraída:

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

Para automatizarlo, puedes envolverlo en un script utilizando branchA y branchB como argumentos.

Esta solución conserva el primer y segundo padre de la confirmación de fusión, tal como cabría esperar de git merge -s theirs branchs .

Las versiones anteriores de git te permitían usar el "suyo" estrategia de fusión:

git pull --strategy=theirs remote_branch

Pero esto ya se ha eliminado, como se explica en este mensaje por Junio ??Hamano (El mantenedor de Git). Como se indica en el enlace, en su lugar, haría esto:

git fetch origin
git reset --hard origin

Tenga cuidado, sin embargo, que esto es diferente a una fusión real. Su solución es probablemente la opción que realmente está buscando.

Utilicé la respuesta de Paul Pladijs desde ahora. Descubrí que puedes hacer un " normal " fusionar, se producen conflictos, por lo que lo hace

git checkout --theirs <file>

para resolver el conflicto utilizando la revisión de la otra rama. Si hace esto para cada archivo, tiene el mismo comportamiento que esperaría de

git merge <branch> -s theirs

De todos modos, ¡el esfuerzo es más de lo que sería con la estrategia de fusión! (Esto se probó con git versión 1.8.0)

No está del todo claro cuál es el resultado deseado, por lo que existe cierta confusión sobre el " correcto " forma de hacerlo en las respuestas y sus comentarios. Intento dar una visión general y ver las siguientes tres opciones:

Intente fusionar y usar B para conflictos

Esta es no la " su versión para git merge -s our " pero la " versión de ellos para git merge -X ours " (que es la abreviatura de git merge -s recursive -X ours ):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

Esto es lo que p. La respuesta de Alan W. Smith sí.

Usar contenido de B solamente

Esto crea una confirmación de fusión para ambas ramas, pero descarta todos los cambios de branchA y solo mantiene el contenido de branchB .

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

Tenga en cuenta que la fusión confirma que el primer padre ahora es el de branchB y solo el segundo es de branchA . Esto es lo que p. La respuesta de Gandalf458 sí.

Use contenido de B solamente y mantenga el orden principal correcto

Esta es la versión real de " su versión para git merge -s our " ;. Tiene el mismo contenido que en la opción anterior (es decir, solo el de branchB ) pero el orden de los padres es correcto, es decir, el primer padre proviene de branchA y el segundo de branchB .

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

Esto es lo que la respuesta de Paul Pladijs (sin requerir una rama temporal).

Resolví mi problema usando

git checkout -m old
git checkout -b new B
git merge -s ours old

Si está en la rama A, haga:

git merge -s recursive -X theirs B

Probado en la versión 1.7.8 de git

  

Al fusionar rama de tema " B " en " A " usando git merge, obtengo algunos conflictos. Sé que todos los conflictos se pueden resolver utilizando la versión en "B".

     

Soy consciente de git merge -s ours. Pero lo que quiero es algo como git merge > -s su.

Supongo que creó una rama fuera de master y ahora desea fusionar nuevamente en master, anulando cualquiera de las cosas antiguas en master. Eso es exactamente lo que quería hacer cuando me topé con esta publicación.

Haz exactamente lo que quieres hacer, excepto combinar primero una rama con la otra. Acabo de hacer esto, y funcionó muy bien.

git checkout Branch
git merge master -s ours

Luego, finalice el proceso de pago y combine su rama en él (ahora se realizará sin problemas):

git checkout master
git merge Branch

Para hacer realmente una fusión que toma solo la entrada de la rama que está fusionando, puede hacer

git merge --strategy = nuestro ref-to-be-merged

git diff --binario ref-to-be-merged | git apply --reverse --index

git commit --amend

No habrá conflictos en ningún escenario que conozca, no tiene que hacer ramas adicionales, y actúa como un compromiso de fusión normal.

Sin embargo, esto no funciona bien con los submódulos.

Consulte la respuesta ampliamente citada de Junio ??Hamano : si va a descartar el compromiso contenido, simplemente descarte las confirmaciones, o al menos manténgalo fuera de la historia principal. ¿Por qué molestar a todos en el futuro leyendo mensajes de confirmación que no tienen nada que ofrecer?

Pero a veces hay requisitos administrativos, o quizás alguna otra razón. Para aquellas situaciones en las que realmente tiene que grabar confirmaciones que no aportan nada, desea:

(edit: wow, me las arreglé para hacerlo mal antes. Este funciona.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard
  

¿Por qué no existe?

Aunque lo menciono en " comando git para crear una rama como otra " cómo simular git merge -s theirs , tenga en cuenta que Git 2.15 (Q4 2017) ahora es más claro:

  

La documentación para ' -X < option > ' para fusiones fue engañosa   escrito para sugerir que " -s suyo " existe, que no es el caso.

Consulte commit c25d98b (25 de septiembre de 2017) por Junio ??C Hamano ( gitster ) .
(Fusionada por Junio ??C Hamano - gitster - en commit 4da3e23 , 28 Sep 2017)

  

estrategias de combinación: evite implicar que " -s his " existe

     

La descripción de la opción de combinación -Xours tiene una nota entre paréntesis   eso le dice a los lectores que es muy diferente de -s our ,   que es correcto, pero la descripción de -Xtheirs que le sigue   dice descuidadamente " esto es lo contrario de our " ;, dando una falsa   impresión de que los lectores también deben ser advertidos de que es muy   diferente de -s theirs , que en realidad ni siquiera existe.

-Xtheirs es una estrategia opción aplicada a la estrategia recursiva. Esto significa que la estrategia recursiva aún combinará todo lo que pueda, y solo recurrirá a " hiss " Lógica en caso de conflictos.

Ese debate sobre la pertinencia o no de una estrategia de fusión suyo se trajo recientemente en este hilo de septiembre de 2017 .
Reconoce hilos más antiguos (2008)

  

En resumen, la discusión anterior se puede resumir en " no queremos ' -s theirs ', ya que fomenta el flujo de trabajo incorrecto " ;.

Menciona el alias:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko intenta abogar una vez más por esa estrategia, pero Junio ??C. Hamano agrega :

  

La razón por la que el nuestro y el suyo no son simétricos es porque usted es usted y no ellos --- el control y la propiedad de nuestra historia y su historia no es simétrica.

     

Una vez que decida que su historial es la línea principal, preferiría tratar su línea de desarrollo como una rama lateral y hacer una fusión en esa dirección, es decir, el primer padre de la combinación resultante es un compromiso en su historial y el segundo padre es el último malo de tu historia. Por lo tanto, terminaría usando " checkout their-history & amp; & amp; fusionar -s our your-history " a   mantener sensata la primera paternidad.

     

Y en ese punto, uso de " -s our " ya no es una solución alternativa por falta de " -s his " ;.
   Es una parte adecuada de la semántica deseada, es decir, desde el punto de vista de la línea de historia canónica sobreviviente, debes conservar lo que hizo, anular lo que hizo la otra línea de la historia .

Este utiliza un comando de git plumbing read-tree, pero hace que el flujo de trabajo sea más corto.

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>

Esto fusionará su newBranch en baseBranch existente

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

Creo que lo que realmente quieres es:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

Esto parece torpe, pero debería funcionar. Lo único que realmente me disgusta de esta solución es que el historial de git será confuso ... Pero al menos el historial se conservará completamente y no tendrá que hacer algo especial para los archivos eliminados.

El equivalente (que mantiene el orden principal) a 'git merge -s theirs branchB'

Antes de fusionar:  ingrese la descripción de la imagen aquí

!!! ¡Asegúrate de estar en estado limpio!

Haz la fusión:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

¿Qué hicimos?  Creamos un nuevo commit en el que dos padres son nuestros y los suyos y el contenido del commit es branchB - suyo

Después de la combinación:  ingrese la descripción de la imagen aquí

Más precisamente:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

Esta respuesta fue dada por Paul Pladijs. Simplemente tomé sus comandos e hice un alias de git para mayor comodidad.

Edite su .gitconfig y agregue lo siguiente:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

Entonces puedes '' fusionar -s de ellos A '' ejecutando:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

Hace poco necesitaba hacer esto para dos repositorios separados que comparten un historial común. Empecé con:

  • Org / repository1 master
  • Org / repository2 master

Quería que todos los cambios de repository2 master se aplicaran a repository1 master , aceptando todos los cambios que haría el repositorio2. En términos de git, este debería ser una estrategia llamada -s her > PERO no existe. Tenga cuidado porque -X suyo se llama como si fuera lo que quiere, pero NO es lo mismo (incluso lo dice en la página del manual).

La forma en que resolví esto fue ir al repository2 y hacer una nueva rama repo1-merge . En esa rama, ejecuté git pull git@gitlab.com: Org / repository1 -s our y se fusiona bien sin problemas. Luego lo empujo al control remoto.

Luego vuelvo al repository1 y hago una nueva rama repo2-merge . En esa rama, ejecuto git pull git@gitlab.com: Org / repository2 repo1-merge que se completará con los problemas.

Finalmente, deberías emitir una solicitud de combinación en repository1 para convertirlo en el nuevo maestro, o simplemente mantenerlo como una rama.

Una forma simple e intuitiva (en mi opinión) de dos pasos para hacerlo es

git checkout branchB .
git commit -m "Picked up the content from branchB"

seguido de

git merge -s ours branchB

(que marca las dos ramas como fusionadas)

La única desventaja es que no elimina los archivos que se han eliminado en la rama B de su rama actual. Posteriormente, se mostrará una diferencia simple entre las dos ramas si existen dichos archivos.

Este enfoque también deja claro, a partir del registro de revisión, lo que se hizo y lo que se pretendía.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top