you when what want tag publicar practices practice good follow delete create crear best git github merge-conflict-resolution

when - publicar tag git



evitar que los archivos con conflictos de fusiĆ³n se comprometan en git (4)

Agregué una prueba de unidad para revisar todos los archivos en el directorio de soluciones para la cadena de marcador de conflicto

[TestClass] public class SolutionValidationTests { [TestMethod] public void CheckForMergeConflicts() { var solutionValidationScripts = new SolutionValidationScripts(); var mergeConflictCheckOkay = solutionValidationScripts.CheckForGitMergeConflict(); Assert.IsTrue(mergeConflictCheckOkay); } }

SolutionValidationScripts definidos por separado a continuación:

public class SolutionValidationScripts { public bool CheckForGitMergeConflict() { var failCount = 0; System.Diagnostics.Debug.WriteLine($"{DateTime.Now.ToString(@"dd-MMM-yyyy HH:mm:ss")}: Starting"); var currentDirectory = System.IO.Directory.GetCurrentDirectory(); var sourceFolder = ""; // Change to suit the build location of your solution sourceFolder = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory()))); // break up the string so this file doesn''t get flagged in the test string searchWord = "<<<<<<< " + "HEAD"; List<string> allFiles = new List<string>(); AddFileNamesToList(sourceFolder, allFiles); for (int i = 0; i < allFiles.Count; i++) { // 35 sec var fileName = allFiles[i]; string contents = File.ReadAllText(fileName); if (contents.Contains(searchWord)) { // For faster result.. no need to continue once a problem is found // throwing an exception here actually works better than an early return to help resolve the issue throw new Exception(fileName); } } return (failCount == 0); } private void AddFileNamesToList(string sourceDir, List<string> allFiles) { string[] fileEntries = Directory.GetFiles(sourceDir); foreach (string fileName in fileEntries) { allFiles.Add(fileName); } //Recursion string[] subdirectoryEntries = Directory.GetDirectories(sourceDir); foreach (string item in subdirectoryEntries) { // Avoid "reparse points" if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint) { AddFileNamesToList(item, allFiles); } } } }

¿Hay alguna forma de evitar que los archivos con conflicto de fusión se comprometan en git? Nadie va a cometer archivos con conflicto intencionalmente. Pero, ¿hay alguna manera de evitar que los archivos se comprometan en git?

¿Tiene git alguna configuración o valores configurables en cualquier lugar, donde pueda evitar archivos buscando los <<<<<<< , ======= o >>>>>>> ?


La respuesta de VonC ya explica los diferentes tipos de enlaces en los que es posible que desee comprobar si hay confirmaciones de combinación.

Si solo desea una solución simple para evitar cometer conflictos, eso ya se incluye con git en el ejemplo de enlace de pre-commit predeterminado. Simplemente habilite el .git/hooks/pre-commit.sample cambiando el nombre de .git/hooks/pre-commit.sample a .git/hooks/pre-commit . Si luego intentas cometer un conflicto:

$ git commit -am "Fix crash in frobnicate" src/foo.c:239: leftover conflict marker

Nota:

La secuencia de comandos usa git diff --check internamente, que también revisa varios problemas de espacios en blanco, por lo que también puede obtener errores de espacios en blanco. También puede ejecutar git diff --check antes de comprometerse a encontrar problemas. Consulte la página de manual de git diff para obtener detalles y opciones de configuración.

Esto es válido para git V2.0; ni idea de cuando fue introducido.


Puede usar un hook pre-commit , pero tenga en cuenta que un git commit --no-verify lo ignorará efectivamente.

Generalmente, coloco un gancho de pre-receive para controlar en un punto central (más) lo que se está empujando.

Pero un pre-commmit permite una detección más oportuna (antes en el ciclo de desarrollo).

Aquí hay otro ejemplo (además del jthill de jthill ), en perl.
Utiliza git diff-index -p -M --cached HEAD , que es git diff-index lugar de git diff .
He dejado algunos otros controles realizados por este gancho, solo para mostrar el tipo de controles que puede hacer en un script de este tipo.

#!/usr/bin/perl use Modern::Perl; use File::Basename; my $nb_errors = 0; my $filepath; for my $l ( split ''/n'', `git diff-index -p -M --cached HEAD` ) { if ( $l =~ /^diff --git a//([^ ]*) .*$/ ) { $filepath = $1; } given ( $l ) { # if there is a file called *.log, stop when ( //.log/ ) { say "$filepath contains console.log ($l)"; $nb_errors++; } # check if there is a warn, that could be unconditionnal, but just warn, don''t stop when ( /^[^(/#|/-)]+warn/ ) { # stay silent if we''re in a template, a "warn" here is fair, it''s usually a message or a css class unless ($filepath =~ //.tt$/) { say "$filepath contains warn ($l)"; } } # check if there is a ` introduced, that is a mysqlism in databases. Can be valid so don''t stop, just warn when (/^/+.*`.*/) { say "$filepath contains a ` ($l)"; } # check if there is a merge conflict marker and just warn (we probably could stop if there is one) when ( m/^<<<<<</ or m/^>>>>>>/ or m/^======/ ) { say "$filepath contains $& ($l)"; } } } if ( $nb_errors ) { say "/nAre you sure you want to commit ?"; say "You can commit with the --no-verify argument"; exit 1; } exit 0;


Un enfoque sencillo utilizando un gancho de precompromiso, adaptado desde here pero mejorado para ser un poco más cuidadoso y completo:

#!/bin/sh changed=$(git diff --cached --name-only) if [[ -z "$changed" ]]; then exit 0 fi echo $changed | xargs egrep ''^[><=]{7}( |$)'' -H -I --line-number # If the egrep command has any hits - echo a warning and exit with non-zero status. if [ $? == 0 ]; then echo "WARNING: You have merge markers in the above files. Fix them before committing." echo " If these markers are intentional, you can force the commit with the --no-verify argument." exit 1 fi

¡No olvide hacer el gancho ejecutable ( chmod u+x pre-commit )!