¿Cuál es el significado preciso de "nuestro" y "suyo" en git?

323

Esto puede parecer una pregunta demasiado básica, pero he buscado respuestas y ahora estoy más confundido que antes.

¿Qué significa "nuestro" y "suyo" en git cuando se fusiona mi rama con la otra? Ambas ramas son "nuestras".

En un conflicto de fusión, ¿es "nuestro" siempre la parte superior de las dos versiones que se muestran?

¿El "nuestro" siempre se refiere a la rama a la que HEAD apuntaba cuando comenzó la fusión? Si es así, ¿por qué no usar una referencia posesiva clara como "rama actual" en lugar de usar un pronombre posesivo como "nuestro" que sea referencialmente ambiguo (dado que ambas ramas son técnicamente nuestras)?

¿O simplemente use el nombre de la sucursal (en lugar de decir "nuestro" solo diga "maestro local" o algo así)?

La parte más confusa para mí es si especifico en el archivo .gitattributes de una rama específica. Digamos que en la rama de prueba tengo el siguiente archivo .gitattributes:

config.xml merge=ours

Ahora pago y apunto HEAD para dominar y luego fusionar en la prueba . Desde maestro es nuestro, y prueba 's .gitattributes no está desprotegido, va a tener incluso un efecto? Si tiene un efecto, ya que el maestro ahora es "nuestro", entonces ¿qué pasará?

Tostada Coma
fuente

Respuestas:

375

Sospecho que estás confundido aquí porque es fundamentalmente confuso. Para empeorar las cosas, todo lo nuestro / lo suyo cambia de roles (se vuelve hacia atrás) cuando estás haciendo un rebase.

En última instancia, durante una git merge, la rama "nuestro" se refiere a la rama que está fusionando en :

git checkout merge-into-ours

y la rama "suya" se refiere a la rama (única) que está fusionando:

git merge from-theirs

y aquí "nuestro" y "ellos" tiene sentido, ya que a pesar de "ellos" es probablemente la suya de todos modos, "el suyo" no es el que usted estaba en cuando ejecutó git merge.

Si bien el uso del nombre real de la sucursal puede ser bastante bueno, se desmorona en casos más complejos. Por ejemplo, en lugar de lo anterior, puede hacer:

git checkout ours
git merge 1234567

donde te estás fusionando por raw commit-ID. Peor aún, incluso puedes hacer esto:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

en cuyo caso no hay nombres de sucursal involucrados!

Creo que es de poca ayuda aquí, pero de hecho, en gitrevisionssintaxis , puede referirse a una ruta individual en el índice por número, durante una fusión en conflicto

git show :1:README
git show :2:README
git show :3:README

La etapa n. ° 1 es el antecesor común de los archivos, la etapa n. ° 2 es la versión de la rama de destino y la etapa n. ° 3 es la versión de la que se está fusionando.


La razón por la cual se intercambian las nociones "nuestra" y "suya" rebasees que el rebase funciona haciendo una serie de selecciones de cereza, en una rama anónima (modo HEAD separado). La rama de destino es la rama anónima, y ​​la rama de fusión es la rama original (previa al rebase): entonces "- nuestro" significa que el rebase anónimo se está construyendo mientras que "- el suyo" significa "nuestra rama está rebaseada" .


En cuanto a la entrada gitattributes: podría tener un efecto: "el nuestro" realmente significa "usar la etapa # 2" internamente. Pero como observa, en realidad no está en su lugar en ese momento, por lo que no debería tener un efecto aquí ... bueno, no a menos que lo copie en el árbol de trabajo antes de comenzar.

Además, por cierto, esto se aplica a todos los usos nuestros y los suyos, pero algunos están en un nivel de archivo completo ( -s ourspara una estrategia de fusión; git checkout --oursdurante un conflicto de fusión) y algunos son pieza por pieza ( -X ourso -X theirsdurante un -s recursiveunir). Lo que probablemente no ayuda con nada de la confusión.

Sin embargo, nunca se me ocurrió un nombre mejor para estos. Y: ¡vea la respuesta de VonC a otra pregunta, donde git mergetoolintroduce aún más nombres para estos, llamándolos "local" y "remoto"!

torek
fuente
28
+1. Sobre los nuestros y los de ellos revertidos durante el rebase, vea también: stackoverflow.com/a/2960751/6309 y stackoverflow.com/a/3052118/6309
VonC
1
Dos cosas "se fusionan" entre sí. Cuando ocurre una fusión, ambas partes se fusionan "entre sí". Creo que sería incorrecto decir que uno de los dos lados "no se está fusionando en nada". Si no hay nombres de sucursal involucrados (como usted señala) entonces hay nombres de compromiso involucrados (podría decir "7777777" y "1234567" en lugar de "nuestro" y "de ellos"). Entiendo lo que sucede durante un rebase y no me parece confuso en absoluto. Creo que "HEAD" y "entrantes" funcionarían mejor que "los nuestros" y "de ellos" porque siempre hay un "HEAD" (ya sea separado o no).
CommaToast
15
Supongo que dado que la cabeza es el asiento de la mente, que es la fuente de identidad, que es la fuente de uno mismo, tiene un poco más de sentido pensar que lo que HEAD señala como "mío" ("nuestro", ya que Supongo que la CABEZA y yo hacemos dos). Si nada más, será un buen dispositivo mnemotécnico.
CommaToast
1
Dicho esto, todavía me gusta hacer una copia física de todo el repositorio antes de hacer algo como rebase ...: D
CommaToast
3
"¡en cuyo caso no hay nombres de sucursal involucrados!" ... Por lo tanto, debería usar el comentario / hash de confirmación. Lo que sea que pueda tener en sus manos. Prácticamente cualquier cosa sería mejor que "la nuestra" y "la de ellos". Me pregunto cuántos miles de horas de desarrollo se ha evaporado esta confusión. la respuesta de git al "análisis más irritante" de C ++;)
Jarrod Smith
49

El ' nuestro ' en Git se refiere a la rama de trabajo original que tiene una parte autorizada / canónica de la historia de git.

El ' suyo ' se refiere a la versión que tiene el trabajo con el fin de ser porcentualizada (cambios para que se reproduzca en la rama actual).

Esto puede parecer intercambiado a personas que no son conscientes de que hacer un rebase (p git rebase. Ej. ) En realidad es suspender su trabajo (que es suyo ) para volver a reproducir la historia canónica / principal que es nuestra , porque estamos cambiando nuestro cambios como trabajo de terceros.

La documentación para git-checkoutse aclaró más en Git> = 2.5.1 según f303016commit :

--ours --theirs

Cuando revise las rutas desde el índice, revise la etapa # 2 ('la nuestra') o # 3 ('la suya') para las rutas no fusionadas.

Tenga en cuenta que durante git rebasey git pull --rebase, 'nuestro' y 'suyo' pueden aparecer intercambiados; --oursproporciona la versión de la rama en la que se vuelven a crear los cambios, mientras que --theirsproporciona la versión de la rama que contiene el trabajo que se está volviendo a crear.

Esto se debe a que rebasese usa en un flujo de trabajo que trata el historial en el control remoto como el canónico compartido, y trata el trabajo realizado en la rama que está cambiando como el trabajo de terceros que se integrará, y usted asume temporalmente el papel de El guardián de la historia canónica durante el rebase. Como el guardián de la historia canónica, debe ver la historia desde el control remoto como ours(es decir, "nuestra historia canónica compartida"), mientras que lo que hizo en su lado se ramifica theirs(es decir, "el trabajo de un colaborador encima").

Porque git-mergese explica de la siguiente manera:

la nuestra

Esta opción obliga a los trozos en conflicto a que se resuelvan automáticamente limpiamente al favorecer nuestra versión. Los cambios del otro árbol que no entran en conflicto con nuestro lado se reflejan en el resultado de la fusión. Para un archivo binario, todo el contenido se toma de nuestro lado.

Esto no debe confundirse con la estrategia de fusión nuestra, que ni siquiera mira lo que contiene el otro árbol. Descarta todo lo que hizo el otro árbol, declarando que nuestra historia contiene todo lo que sucedió en él.

suyo

Esto es lo opuesto al nuestro.

Además, aquí se explica cómo usarlos:

El mecanismo de fusión ( git mergey git pullcomandos) permite elegir las estrategias de fusión de back-end con -sopción. Algunas estrategias también pueden tomar sus propias opciones, que pueden pasarse dando -X<option>argumentos git mergey / o git pull.


Entonces, a veces puede ser confuso, por ejemplo:

  • git pull origin masterdonde -Xoursestá nuestro local, -Xtheirses su sucursal (remota)
  • git pull origin master -rdonde -Xoursestá el de ellos (remoto), -Xtheirses nuestro

Entonces, el segundo ejemplo es opuesto al primero, porque estamos cambiando nuestra rama por encima de la remota, por lo que nuestro punto de partida es remoto y nuestros cambios se tratan como externos.

Similar para las git mergeestrategias ( -X oursy -X theirs).

kenorb
fuente
2
esta respuesta parece desactualizada => "git merge --ours" no es una opción válida
Alexander Mills
@AlexanderMills La respuesta no habló git merge, pero git pully git checkoutcomo ejemplo. Si desea usar este parámetro con git merge, debe usar -X ours. Todavía puede usar la --ourssintaxis para git checkout. He aclarado la respuesta aún más.
kenorb
46

Sé que esto ha sido respondido, pero este problema me confundió tantas veces que he puesto un pequeño sitio web de referencia para ayudarme a recordar: https://nitaym.github.io/ourstheirs/

Aquí están los conceptos básicos:

Fusiones

$ git checkout master 
$ git merge feature

Si desea seleccionar la versión en master:

$ git checkout --ours codefile.js

Si desea seleccionar la versión en feature:

$ git checkout --theirs codefile.js

Rebases:

$ git checkout feature 
$ git rebase master 

Si desea seleccionar la versión en master:

$ git checkout --ours codefile.js

Si desea seleccionar la versión en feature:

$ git checkout --theirs codefile.js

(Esto es para archivos completos, por supuesto)

Nitay
fuente
1
Ese sitio web es muy útil. El estilo de diagrama de flujo y las palabras codificadas por colores hacen que el sitio web sea mucho más fácil de entender que las respuestas SO. Gracias.
Ron
10
  • Nuestra : Esta es la sucursal en la que se encuentra actualmente.
  • La suya : esta es la otra rama que se utiliza en su acción.

Así que si usted está en la rama de la liberación / 2.5 y combinar rama / nuevos botones de función en ella, a continuación, el contenido que se encuentra en la liberación / 2.5 es lo nuestro se refiere y el contenido que se encuentra en / nuevos botones de función es lo suyo se refiere a. Durante una acción de fusión, esto es bastante sencillo.

El único problema del que se enamora la mayoría de las personas es el caso de rebase . Si realiza una re-base en lugar de una fusión normal, los roles se intercambian. ¿Como es que? Bueno, eso es causado únicamente por la forma en que funciona el rebase. Piensa en rebase para trabajar así:

  1. Todas las confirmaciones que ha realizado desde su última extracción se trasladan a una rama propia, nombremos BranchX .
  2. Revisa el encabezado de su rama actual, descartando cualquier cambio local que haya tenido, pero de esa manera recupera todos los cambios que otros han empujado para esa rama.
  3. Ahora, cada confirmación en BranchX se selecciona de forma antigua a nueva en su rama actual.
  4. BranchX se elimina nuevamente y, por lo tanto, nunca aparecerá en ningún historial.

Por supuesto, eso no es realmente lo que está sucediendo, pero es un buen modelo mental para mí. Y si observa 2 y 3, comprenderá por qué los roles se intercambian ahora. A partir de 2, su rama actual es ahora la rama del servidor sin ninguno de sus cambios, por lo que esta es la nuestra (la rama en la que se encuentra). Los cambios que realizó ahora están en una rama diferente que no es la actual ( BranchX ) y, por lo tanto, estos cambios (a pesar de ser los cambios que realizó) son suyos (la otra rama utilizada en su acción).

Eso significa que si te unes y quieres que tus cambios siempre ganen, le dirías a git que siempre elija "el nuestro", pero si cambias de opinión y quieres que todos tus cambios siempre ganen, le dices a git que siempre elija "el suyo".

Mecki
fuente
3

Sé que no explica el significado, pero me hice una pequeña imagen, como referencia para recordar cuál usar:

ingrese la descripción de la imagen aquí

¡Espero eso ayude!

PD: marque también el enlace en la respuesta de Nitay 🙂

Kamafeather
fuente
3

Publicaré mi memorando aquí, porque tengo que volver aquí una y otra vez.

ESCENARIO 1. Desarrollador normal: Eres un desarrollador que no puede fusionarse mastery solo tiene que jugar con featureramas.

Caso 1: el maestro es un rey. Desea actualizar su featurerama (= rebase a master), porque mastercontiene nuevas actualizaciones de dependencias y desea sobrescribir sus modestos cambios.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Caso 2: eres un rey. Desea cambiar su featurerama a los mastercambios. Pero hizo más de lo que sus colegas hicieron y quiere usar sus propios cambios en una prioridad.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

IMPORTANTE: Como puede ver, los desarrolladores normales deberían preferir rebasey repetirlo todas las mañanas como ejercicios / café.

ESCENARIO 2. Merging-sensei: Usted es un líder de equipo y desea fusionar otras ramas e impulsar un resultado combinado directamente a un maestro. masteres una rama que cambiarás.

Caso 1: el maestro es un rey Quiere fusionar una sucursal de terceros, pero masteres una prioridad. featurees una rama que tu superior hizo.

git checkout feature
git pull

git checkout master
git merge -X ours master

Caso 2: los nuevos cambios son un rey Cuando su desarrollador senior lanzó un genial featurey desea sobrescribir el viejo s ** t en la masterrama.

git checkout feature
git pull

git checkout master
git merge -X theirs master

RECUERDE: Recordar a medianoche cuál elegir: SIEMPRE masteres ours. Y theirses algo featureque ellos han hecho.

DenisKolodin
fuente
2

Del git checkoutuso de:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

Al resolver conflictos de fusión, puede hacerlo git checkout --theirs some_filey git checkout --ours some_filerestablecer el archivo a la versión actual y las versiones entrantes respectivamente.

Si lo ha hecho git checkout --ours some_fileo git checkout --theirs some_filedesea restablecer el archivo a la versión de combinación de 3 vías, puede hacerlo git checkout --merge some_file.

Joshua Ryan
fuente