¿Cómo seleccionar un archivo de una rama al resolver un conflicto durante git rebase?

5 minutos de lectura

Dado un repositorio git con dos ramas master y feature. Al volver a basar la rama de características en la parte superior del maestro usando rebase master digamos ese archivo a.txt contiene un conflicto que debe resolverse antes de que la reorganización pueda continuar.

Sé que puedo resolver el conflicto en tres pasos:

  1. abierto a.txt en mi editor resolver manualmente el conflicto
  2. llamar git add a.txt para decirle a git que he resuelto manualmente el conflicto
  3. llamar git rebase --continue mover la rebase hacia adelante

¿Hay alguna manera de evitar el paso 1 diciéndole a git que quiero la versión del archivo de la rama maestra o quiero la versión del archivo de la rama de funciones sin tener que realizar los pasos 1 y 2 anteriores?

avatar de usuario de torek
Torek

Sí. De hecho, hay más de una manera de hacerlo.

Los comandos rebase y merge (y cherry-pick, para el caso) toman todos los mismos strategy y -X banderas para pasar a la maquinaria subyacente de git merge. Para el recursive estrategia, -Xours y -Xtheirs elegir uno u otro “lado” de los archivos en el caso de que se fusione un archivo modificado en ambas ramas.

O, esto es bastante diferente, en los casos en que fusionar se detiene con un conflictopuedes usar git checkout con el --ours o --theirs banderas, para elegir la versión de un lado o del otro. (Puedes hacer esto con otros comandos; aquí, me quedaré con --ours y --theirs ya que estos coinciden con los argumentos de los comandos que usan la maquinaria de combinación).

Por supuesto, esto es diferente porque puede cambiar las opciones:

$ git checkout main
Switched to branch 'main'
$ git merge branch
... conflicts in files A and B ...
$ git checkout --ours -- A    # takes main:A
$ git checkout --theirs -- B  # takes branch:B

Tenga en cuenta que esto es bastante diferente del “nuestro estrategia” (lo anterior muestra el “recursive estrategia con la ours opción”). Con el “nuestro estrategia“, ocurre algo completamente diferente. Comencemos sin él, haciendo la misma combinación nuevamente:

$ git checkout main && git merge branch
... conflicts ...
$ git checkout --ours -- A B  # take main:A and main:B

Digamos que hay un tercer archivo, C, ese git puede fusionarse por sí solo. Cuando haces lo anterior, git se fusiona C y tu tomas main:A y main:B. Si fueras a usar git merge --strategy=ours branchsin embargo, git tomaría main:A, main:By main:C. descartaría la branch:C cambios en lugar de fusionarlos automáticamente.

he usado git merge anterior porque hace que las cosas “nuestras” y “suyas” “funcionen bien”. Sin embargo, no me gusta la forma en que git los nombra, porque cuando estás haciendo una rebase, la versión nuestra/suya se intercambia, porque la rebase funciona cambiando a la rama “otra” y haciendo una serie de selecciones. Eso es:

$ git checkout mine; git rebase theirs

funciona debajo haciendo el equivalente (muy) aproximado de:

$ git checkout theirs; git cherry-pick theirs..mine

y luego, barajar las etiquetas de las ramas para que esa rama theirs en realidad no se mueve. (No es tan malo internamente 🙂 pero logra hacer --ours significa “suyo” y --theirs significa “nuestro”, lo cual es bastante malo externamente.)

  • gracias por explicar por qué la rebase cambia entre las etiquetas nuestras y de ellos.

    – ams

    31 de enero de 2014 a las 22:22

  • @torek Siempre me encantan tus respuestas. P: es git merge --strategy=ours igual a git merge --ours --file_with_conflict1 --file_with_conflict2 ... --file_with_conflict_n donde ‘file_with_conflict1’, … ‘file_with_conflict_n’ son todos los archivos con conflictos de combinación?

    – Diana

    22 de enero a las 2:17

  • @Diana: git merge no toma --ours. ¿Estás pensando en git merge-file? (Su uso es diferente, pero tiene --ours.)

    – torek

    22 de enero a las 2:58

  • @torek ¡Vaya! lo siento reformule mi pregunta aquí: a. git merge --strategy=ours b. git merge después git checkout --ours --file_with_conflict1 --file_with_conflict2 ... --file_with_conflict_n donde ‘file_with_conflict1’, … ‘file_with_conflict_n’ son todos los archivos con conflictos de combinación? ¿Son (a) y (b) equivalentes?

    – Diana

    24 de enero a las 14:57


  • @Diana: Ah. No porque git merge sin que -s ours intenta fusiones para cada archivo. Algunos de estos tendrán éxito sin conflicto, combinando así el trabajo. Otros tendrán conflictos; la git checkout --ours pues esos archivos desecharán su trabajo, llevándose sólo el nuestro. Entonces obtendremos una mezcla: algunos archivos exclusivamente de nosotros (donde cambiamos un archivo y ellos no lo hicieron, o donde hubo un conflicto), algunos exclusivamente de ellos (donde ellos cambiaron un archivo y nosotros no lo hicimos), y algunos combinados (donde merge pudo combinar el trabajo sin conflictos). Pero con -s nuestro, Git lo hará ignorar su trabajo.

    – torek

    24 de enero a las 16:37


Avatar de usuario de Ash Wilson
ash wilson

Puedes usar:

git checkout --ours -- path/to/file

O:

git checkout --theirs -- path/to/file

…durante una fusión o reorganización para elegir una versión particular de un archivo en conflicto; porque rebasar es un poco extraño, --theirs en este caso seria featurela versión de, --ours sería master‘s.

  • en realidad, tu no Necesitar git add, porque la comprobación escribe “a través del índice”, copiando la versión nuestra o de ellos en la “ranura 0” del índice antes de escribirla en el árbol de trabajo. (Haciendo git add aunque es inofensivo).

    – torek

    31 de enero de 2014 a las 22:10


  • ¿Ah, de verdad? Pensé que también tenía que escenificarlo, escenificarlo como una resolución. Actualizaré la respuesta, gracias!

    – Ceniza Wilson

    31 de enero de 2014 a las 22:12

Creo que lo que estás buscando, que se librará de los tres pasos, es

git rebase master -X theirs

que resolverá automáticamente los conflictos a favor de feature (la sucursal actualmente desprotegida), o

git rebase master -X ours

El sentido de ours y theirs es contrario a la intuición como argumentos para rebase, como se indica en la descripción de la opción en http://git-scm.com/docs/git-rebase

  • Si hay dos archivos en conflicto a.txt y b.txt, es posible que desee seleccionar a.txt de la rama maestra y b.txt, es posible que desee fusionarlos manualmente. ¿Los comandos que sugiere se aplican a todos los archivos en conflicto?

    – ams

    31 de enero de 2014 a las 22:07


  • En ese caso, la respuesta de Ash Wilson es la indicada 🙂

    – GreenAsJade

    31 de enero de 2014 a las 22:09

¿Ha sido útil esta solución?