Git merge su Windows con file duplicati

Oct 02 2020

Ho problemi a sincronizzare un ramo locale con un telecomando, so perché e ho una soluzione, ma vorrei sapere se esiste una soluzione migliore.

Fattori rilevanti:

  1. È per un ramo gh-pages condiviso; quindi nessuno sviluppo attivo sul ramo
  2. Lavoro su Windows (e non riesco ad attivare facilmente il supporto Posix per nomi di file sensibili al maiuscolo / minuscolo).
  3. Il repository contiene due file che differiscono solo per maiuscole e minuscole per i nomi dei file, cioè si sovrascriveranno l'un l'altro!
  4. Voglio aggiungere altri file
  5. E sincronizza questo ramo con il telecomando (usando merge / pull).

Gli elementi 2 e 3 indicano che il solo check-out dei file crea una modifica, poiché una variante del caso sovrascrive l'altra.

Tuttavia, gli elementi 1-4 possono ancora essere gestiti creando un nuovo ramo locale, mettendo in scena e salvando i nuovi file e ignorando gli avvisi.

Ma unire / tirare ecc fallisce; poiché i file con conflitti tra maiuscole e minuscole causano problemi.

Soluzione:

Elimina il ramo locale e creane uno nuovo basato sul remoto (supponendo che non ci siano modifiche locali).

Risposte

1 torek Oct 02 2020 at 18:26

Non è necessario eliminare alcun ramo ma dovrai stare attento con il tuo albero di lavoro .

Ricorda che ciò che Git utilizza effettivamente, sia per controllare qualsiasi commit esistente, sia per creare qualsiasi nuovo commit, è l' indice di Git . Git chiama anche questa entità l' area di sosta , che riflette il suo ruolo nel fare nuovi commit, e, anche se in questi giorni si lo più vedere questo come una bandiera, --cached-la della cache , che riflette il ruolo dell'indice nel fare Git andare veloce.

I file archiviati nell'indice fanno distinzione tra maiuscole e minuscole, quindi l'indice di Git è in grado di contenere due file separati denominati a/readme.txte A/README.TXT, ad esempio. Tieni presente che i file nell'indice sono rappresentati con nomi di percorso che utilizzano barre e questo a/readme.txtè un nome di file: non ci sono cartelle nell'indice, solo file con barre incorporate nei loro nomi.

I file che si trovano in l'indice sono memorizzati in forma interna di Git. Questo non ti è utile: questi file sono in un formato di dati compresso, di sola lettura e di sola Git. Quindi Git espande ciascuno di questi file in un normale file di lettura / scrittura di tutti i giorni. Questo normale file di lettura / scrittura va in una cartella e ha un normale nome di file di tutti i giorni. Ma questo significa che quando Git va a scrivere entrambi a/readme.txt, il che richiede la creazione di una cartella denominata ae un file denominato readme.txtin essa, e A/README.TXT, che richiede la creazione di una cartella denominata Ae un file denominato README.TXTin quella , si ottiene una collisione di nomi. Solo una cartella e un solo file vengono effettivamente creati.

L'indice continua a tenere entrambi i file , a/readme.txte A/README.TXT. Utilizzando uno dei cosiddetti di Git comandi idraulici , git update-index, è possibile (ma molto difficile e fastidioso) per aggiornare entrambi questi file. Ricorda che mentre l'indice contiene i file in frozen-e-compressa del Git formato , è possibile sostituire i file all'ingrosso questi indice, a condizione che:

  1. comprimere i dati nel formato interno di Git, producendo quello che Git chiama un ID hash del blob ;
  2. fornire git update-indexil nome del file, ad esempio a/readme.txt, e l'ID hash del BLOB.

I dati da inserire nell'oggetto BLOB interno possono provenire da qualsiasi file in qualsiasi punto del computer. Non deve nemmeno essere nel tuo albero di lavoro: può essere lì o altrove. Utilizzare git hash-object -wper creare l'oggetto BLOB interno e salvare l'ID hash risultante in una variabile. Quindi, esegui immediatamente git update-indexper sostituire la copia dell'indice del file.

Per informazioni su come utilizzare ciascuno di questi due comandi idraulici di basso livello, vedere la relativa documentazione: git hash-objecte git update-index.

Nota che questi due comandi non sono realmente pensati per l'uso da parte degli esseri umani: sono pensati per essere eseguiti da programmi più orientati all'uomo e sono solo elementi costitutivi che i comandi amano git adde git rmpossono usare. Il problema con l'utilizzo di git adde git rmqui è che quei programmi vogliono lavorare con i file dell'albero di lavoro, utilizzando i nomi trovati sul computer, ad esempio, A\README.TXTinvece che con i nomi dei file interni di Git. Ecco perché dovresti usare i comandi di basso livello, in modo da poter memorizzare entrambi i dati dei file interni di Git ( a/readme.txte A/README.TXT) in file con nomi diversi, quindi aggiornare i file interni di Git da quei nomi diversi.

Modifica: ho dimenticato di dire che dovrai leggere i due file. Ci sono diversi modi per farlo, ma probabilmente il più semplice è usare git showcon il reindirizzamento in stile shell. In sh / bash, dovresti eseguire:

git show HEAD:a/readme.txt > lowercase-readme
git show HEAD:A/README.TXT > uppercase-readme

per ottenere entrambi i file, con due nomi diversi, nel tuo albero di lavoro. Git infatti estrarrà entrambi i file durante git checkout, ma finiranno per occupare un singolo file dell'albero di lavoro, il cui nome potrebbe essere readme.txto README.TXT, a seconda di quale nome "vince" la competizione get-a-Windows-file-name; questo file potrebbe apparire in una cartella denominata ao in una cartella denominata , a Aseconda di quale di questi "vince" il concorso "get a-windows-folder-name".