¿Cómo fusionará Git esto?

John y Tom clonan el mismo repository remoto. El contenido del repository remoto es así:

FileA.c 

John realiza una confirmación local como esta, es decir, mueve el FileA.c a una carpeta llamada John y la confirma localmente.

 John\FileA.c 

Tom también hace una confirmación local como esta, es decir, mueve el FileA.c a una carpeta llamada Tom y la confirma localmente.

 Tom\FileA.c 

Si Tom y John empujan sus repos locales al repository remoto, digamos GitHub, ¿cómo combinará Git esto?

Espero haber sido claro. ¡Gracias!

Cuando haces git commit pero no haces git push , los cambios se agregan en tu repository local y no están comprometidos con el repository global. Entonces, cualquiera que presione sus cambios primero, no tendrá ningún conflicto ya que el server remoto no sabe acerca de los cambios realizados por otros usuarios que aún no se han pushed . Más adelante, cuando el siguiente usuario intente insert los cambios, git dará el error de que el repository global ha sido modificado y usted debe primero hacer los cambios. Como los cambios están en el mismo file y la location ha cambiado, habrá un conflicto, que no será resuelto por el propio git. El siguiente usuario tendrá que hacer los cambios nuevamente y presionarlo para actualizar el repository global.

Git / SVN / etc, realice una fusión lo mejor posible: si ven que se han agregado / eliminado / modificado líneas de código separadas que no interfieren, entonces simplemente combinarán los cambios realizados por John / FileA.c y Karen / FileA.c (se convierte en práctica para hacer que alguien en tu ejemplo sea una niña = P). Si el script de combinación ve que las mismas líneas de código han sido editadas, entonces lo marcará como un conflicto en el file.

Creo que se ha hecho este punto, pero este process ocurre localmente; ya sea por Karen o John, dependiendo de quién fue la persona que intentó y empujó al último. Se notificará a la persona que presionó el último para que extraiga del repository remoto y resuelva cualquier conflicto antes de impulsar sus propios cambios.

Git nunca se fusionará durante el push . Uno de los dos desarrolladores (el que intenta empujar el último) tiene que resolver el conflicto localmente y decirle a git dónde mover el file. Git no puede saber dónde debe terminar el file sin intervención humana.

 # dev1 git clone … mkdir John && git mv FileA.c John/FileA.c git commit -m 'move file to john subdir' git push origin master # dev2 git clone … mkdir Tom && git mv FileA.c Tom/FileA.c git commit -m 'move file to tom subdir' git push origin master # git errors out: non-fast-forward, pull first to resolve potential conflicts git pull origin master # merge conflict in FileA.c # tell git which file to delete and which file to keep: git rm Tom/FileA.c && git add John.FileA.c git commit # creates a merge commit git push origin master 

Una segunda operación de inserción fallará; fusión tiene que hacerse localmente. En este caso, habrá un conflicto que debe resolverse manualmente.

Lo bueno de git es que es fácil probar estas cosas por ti mismo sin afectar a ningún server. El resultado para el último tipo que empuja es:

 02:32:54 ~/desktop/tom $ git push To /cygdrive/h/desktop/test ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '/cygdrive/h/desktop/test' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (eg 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details. 02:32:54 ~/desktop/tom $ git pull remote: Counting objects: 3, done. remote: Total 2 (delta 0), reused 0 (delta 0) Unpacking objects: 50% (1/2) Unpacking objects: 100% (2/2) Unpacking objects: 100% (2/2), done. From /cygdrive/h/desktop/test 307f68a..2539f44 master -> origin/master error: refusing to lose untracked file at 'John/FileA.c' error: refusing to lose untracked file at 'John/FileA.c' CONFLICT (rename/rename): Rename "FileA.c"->"Tom/FileA.c" in branch "HEAD" rename "FileA.c"->"John/FileA.c" in "2539f448bb15d10f14bef74688dc3470975c2dbf" CONFLICT (rename/rename): Rename "FileA.c"->"Tom/FileA.c" in branch "HEAD" rename "FileA.c"->"John/FileA.c" in "2539f448bb15d10f14bef74688dc3470975c2dbf" Automatic merge failed; fix conflicts and then commit the result 

Git es agradable y pregunta qué cambio de nombre es el correcto. Tenga en count que no todos los sistemas de control de versiones son capaces de detectar este tipo de conflicto de cambio de nombre / cambio de nombre.

El punto key de las otras respuestas es que git no adivina lo que debería suceder [usando una presunción precodificada], sino que advertirá al usuario de la dificultad porque no puede leer las intenciones del usuario.

La mayoría de los otros sistemas que afirman tener la capacidad de hacer tales fusiones no pasan la testing de clarividencia, no saben lo que realmente querías. Deja que la gente inteligente (somos tú y yo 😉 tome las decisiones.