En la instancia específica de un archivo de configuración, estaría de acuerdo con la respuesta de Ron :
una configuración debe ser "privada" para su espacio de trabajo (por lo tanto, "ignorada", como en "declarada en un .gitignore
archivo").
Puede tener una plantilla de archivo de configuración con valores tokenizados y una secuencia de comandos que transforma ese config.template
archivo en un archivo de configuración privado (e ignorado).
Sin embargo, esa observación específica no responde a lo que es una pregunta más general y más amplia, es decir, su pregunta (!):
¿Cómo le digo a git que siempre seleccione mi versión local para combinaciones conflictivas en un archivo específico? (para cualquier archivo o grupo de archivos)
Este tipo de fusión es una "fusión de copia", en la que siempre copiará la versión "nuestra" o "suya" de un archivo siempre que haya un conflicto.
(como señala Brian Vandenberg en los comentarios , ' ours
' y ' theirs
' se utilizan aquí para una combinación .
Se invierten para una rebase : consulte " Why is the meaning of “ours” and “theirs” reversed with git-svn
", que utiliza una rebase, " git rebase
, realizando un seguimiento de 'local' y 'remoto' " )
Para "un archivo" (un archivo en general, sin hablar de un archivo de "configuración", ya que es un mal ejemplo), lo lograría con un script personalizado llamado mediante fusiones.
Git llamará a ese script porque habrá definido 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, por lo que le permitirá seleccionar siempre su versión local.
. Es decir, como señaló por Ciro Santilli :
echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true
Probemos 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, creemos 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 de git diferentes:
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
- excepto por
dirWithCopyMerge\b.txt
donde siempre quiero mantener mi versión de b.txt
.
Dado que la fusión se produce en " MyBranch
", volveremos a utilizarla y agregaremos las gitattributes
directivas " " 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 .gitattributes
archivo definido en el dirWithCopyMerge
directorio (definido solo en la rama donde ocurrirá la fusión :) myBranch
, y tenemos un .git\config
archivo que ahora contiene un controlador de fusión.
[merge "keepMine"]
name = always keep mine during merge
driver = keepMine.sh %O %A %B
Si aún no define keepMine.sh y ejecuta la combinació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 un conflicto
b.txt
aún está intacto, ya que se supone que el controlador de combinación se encarga de ello (debido a la directiva en el .gitattributes
archivo en su directorio).
Defina un keepMine.sh
en cualquier lugar 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 se ha comentado por lrkwz , y se describe en el " Combinar estrategias sección" de Personalización de Git - Git atributos , puede reemplazar el script de shell con el comando 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 conductor de combinación sencilla;) (Incluso más sencillo en ese caso, el uso true
)
(Si quería mantener la otra versión, sólo tiene que añadir antes de la exit 0
línea:
cp -f $3 $2
.
Eso es todo Combinar conductor tendría tiendas de comida para mantener la versión procedente del otro. rama, anulando cualquier cambio local)
Ahora, volvamos a intentar 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 un.txt .
Edite un.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 ha conservado durante esta fusión
type dirWithCopyMerge\b.txt
b
myLineForB
La última confirmación representa la fusió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 prueba eso)
Considere que puede definir, combinar y / o sobrescribir el controlador de combinación, ya que Git lo hará:
- examinar
<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 lo ha hecho
- Finalmente examina
$GIT_DIR/info/attributes
. Este archivo se utiliza para anular la configuración del árbol. Sobrescribirá las <dir>/.gitattributes
directivas.
Por "combinar", me refiero a un controlador de combinación múltiple "agregado".
Nick Green intenta, en los comentarios , combinar los controladores de combinación: consulte " Combinar pom a través del controlador git de python ".
Sin embargo, como mencionó en su otra pregunta , solo funciona en caso de conflictos (modificación concurrente en ambas ramas).