remota ramas rama fusionar example crear git git-merge

ramas - git merge example



¿Cómo le digo a git que siempre seleccione mi versión local para las fusiones en conflicto en un archivo específico? (2)

Digamos que estoy colaborando con alguien a través de un repositorio de git, y hay un archivo en particular en el que no quiero aceptar ningún cambio externo.

¿Hay alguna forma de configurar mi repositorio local para que no me queje de una fusión conflictiva cada vez que lo hago? Me gustaría seleccionar siempre mi versión local al fusionar este archivo.


En la instancia específica de un archivo de configuración, estoy de acuerdo con la respuesta de Ron :
una configuración debe ser "privada" para su espacio de trabajo (por lo tanto "ignorado", como en "declarado en un archivo .gitignore ").
Puede tener una plantilla de archivo de configuración con valores tokenizados y un script que transforma ese archivo config.template en un archivo de configuración privado (e ignorado).

Sin embargo, esa observación específica no responde a una pregunta más general, es decir, su pregunta (!):

¿Cómo le digo a git que siempre seleccione mi versión local para las fusiones en conflicto en un archivo específico? (para cualquier archivo o grupo de archivos)

Este tipo de fusión es una "combinación de copia", en la que siempre copiará la versión de un archivo "suya" o "suya" siempre que haya un conflicto.

(Como señala Brian Vandenberg en los comentarios , " ours " y " theirs " se utilizan aquí para una fusión .
Se invierten para una rebase : ver " Why is the meaning of “ours” and “theirs” reversed with git-svn se invierte Why is the meaning of “ours” and “theirs” reversed with git-svn ", que utiliza una rebase, " git rebase , git rebase seguimiento de ''local'' y ''remoto'' ")

Para "un archivo" (un archivo en general, sin hablar de un archivo "config", ya que es un mal ejemplo), lo lograría con un script personalizado llamado a través de fusiones.
Git llamará a esa secuencia de comandos porque tendrá que definir un valor de gitattributes , que define un controlador de combinación personalizado .

El "controlador de combinación personalizado" es, en este caso, un script muy simple que básicamente mantendrá sin cambios la versión actual, lo que le permite seleccionar siempre su versión local.

Vamos a probar eso en un escenario simple, con un msysgit 1.6.3 en Windows, en una mera sesión de DOS:

cd f:/prog/git/test mkdir copyMerge/dirWithConflicts mkdir copyMerge/dirWithCopyMerge cd copyMerge git init Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/

Ahora, hagamos dos archivos, que tendrán conflictos, pero que se fusionarán de manera diferente.

echo a > dirWithConflicts/a.txt echo b > dirWithCopyMerge/b.txt git add -A git commit -m "first commit with 2 directories and 2 files" [master (root-commit) 0adaf8e] first commit with 2 directories and 2 files

Introduciremos un "conflicto" en el contenido de ambos archivos en dos ramas diferentes de git:

git checkout -b myBranch Switched to a new branch ''myBranch'' echo myLineForA >> dirWithConflicts/a.txt echo myLineForB >> dirWithCopyMerge/b.txt git add -A git commit -m "add modification in myBranch" [myBranch 97eac61] add modification in myBranch git checkout master Switched to branch ''master'' git checkout -b hisBranch Switched to a new branch ''hisBranch'' echo hisLineForA >> dirWithConflicts/a.txt echo hisLineForB >> dirWithCopyMerge/b.txt git add -A git commit -m "add modification in hisBranch" [hisBranch 658c31c] add modification in hisBranch

Ahora, intentemos fusionar "hisBranch" en "myBranch", con:

  • resolución manual para fusiones conflictivas
  • a excepción de dirWithCopyMerge/b.txt donde siempre quiero mantener mi versión de b.txt .

Dado que la fusión se produce en '' MyBranch '', volveremos a ella y agregaremos las directivas '' gitattributes '' que personalizarán el comportamiento de fusión.

git checkout myBranch Switched to branch ''myBranch'' echo b.txt merge=keepMine > dirWithCopyMerge/.gitattributes git config merge.keepMine.name "always keep mine during merge" git config merge.keepMine.driver "keepMine.sh %O %A %B" git add -A git commit -m "prepare myBranch with .gitattributes merge strategy" [myBranch ec202aa] prepare myBranch with .gitattributes merge strategy

Tenemos un archivo .gitattributes definido en el directorio dirWithCopyMerge (definido solo en la rama donde se producirá la fusión: myBranch ), y tenemos un archivo .git/config que ahora contiene un controlador de combinación.

[merge "keepMine"] name = always keep mine during merge driver = keepMine.sh %O %A %B

Si aún no define keepMine.sh e inicia la fusión de todos modos, esto es lo que obtiene.

git merge hisBranch sh: keepMine.sh: command not found fatal: Failed to execute internal merge git st # On branch myBranch # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: dirWithConflicts/a.txt # no changes added to commit (use "git add" and/or "git commit -a") type dirWithConflicts/a.txt a <<<<<<< HEAD:dirWithConflicts/a.txt myLineForA ======= hisLineForA >>>>>>> hisBranch:dirWithConflicts/a.txt

Eso está bien:

  • a.txt está listo para fusionarse y tiene conflicto en él
  • b.txt sigue intacto, ya que se supone que el controlador de combinación se ocupará de él (debido a la directiva en el archivo .gitattributes en su directorio).

Defina un keepMine.sh en cualquier parte de su %PATH% (o $PATH para nuestro amigo de Unix. Yo hago ambas cosas, por supuesto: tengo una sesión de Ubuntu en una sesión de VirtualBox)

Como lo commented lrkwz , y se describe en la sección " Merge Strategies " de Customizing Git-Git Attributes , puede reemplazar el script de shell con el comando de shell true .

git config merge.keepMine.driver true

Pero en el caso general, puede definir un archivo de script:

keepMine.sh

# I want to keep MY version when there is a conflict # Nothing to do: %A (the second parameter) already contains my version # Just indicate the merge has been successfully "resolved" with the exit status exit 0

(que era un controlador de combinación simple;) (Incluso más simple en ese caso, use true )
(Si desea conservar la otra versión, solo agregue antes de la línea de exit 0 :
cp -f $3 $2 .
Eso es. El controlador de fusión siempre mantendrá la versión procedente de la otra rama, anulando cualquier cambio local)

Ahora, reintentemos la fusión desde el principio:

git reset --hard HEAD is now at ec202aa prepare myBranch with .gitattributes merge strategy git merge hisBranch Auto-merging dirWithConflicts/a.txt CONFLICT (content): Merge conflict in dirWithConflicts/a.txt Auto-merging dirWithCopyMerge/b.txt Automatic merge failed; fix conflicts and then commit the result.

La fusión falla ... solo para a.txt .
Edite a.txt y deje la línea de ''hisBranch'', luego:

git add -A git commit -m "resolve a.txt by accepting hisBranch version" [myBranch 77bc81f] resolve a.txt by accepting hisBranch version

Comprobemos que b.txt se haya conservado durante esta fusión

type dirWithCopyMerge/b.txt b myLineForB

La última confirmación representa la combinación completa :

git show -v 77bc81f5e commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d Merge: ec202aa 658c31c git merge hisBranch Already up-to-date.

(La línea que comienza con Merge lo prueba)

Considere que puede definir, combinar y / o sobrescribir el controlador de combinación, ya que Git:

  • examine <dir>/.gitattributes (que está en el mismo directorio que la ruta en cuestión): prevalecerá sobre el otro .gitattributes en directorios
  • Luego examina .gitattributes (que está en el directorio principal), solo establecerá directivas si aún no se ha establecido
  • Finalmente, se analiza $GIT_DIR/info/attributes . Este archivo se usa para anular la configuración en el árbol. <dir>/.gitattributes directivas <dir>/.gitattributes .

Al "combinar", me refiero a un controlador de combinación múltiple "agregado".
Nick Green intenta, en los comentarios , combinar realmente los controladores de combinación: ver " Merge pom''s via python git driver ".
Sin embargo, como se menciona en su otra pregunta , solo funciona en caso de conflictos (modificación concurrente en ambas ramas).


Tenemos múltiples archivos de configuración que nunca queremos sobrescribir. Sin embargo, .gitignore y .gitattributes no funcionaron en nuestra situación. Nuestra solución fue almacenar los archivos de configuración en una rama de configuración. Luego, permite que los archivos se cambien durante la fusión de git, pero inmediatamente después de la fusión utiliza la "rama de git checkout -". para copiar nuestros archivos de configuración de la rama configs después de cada fusión. Respuesta detallada aquí