È ansible escludere specifici commit quando si fa un git merge?

Diciamo che voglio unire da un ramo di release al ramo master e che ci sono alcuni commit nel ramo di release che non voglio includere nel ramo master. C’è un modo per eseguire l’unione in modo che uno o più di questi commit non vengano uniti?

La mia strategia finora è quella di fare quanto segue (in master):

git merge --no-commit release-branch # Resolve conflicts and apply reverse patch of the commits that I don't want included git commit # Edit commit message so that it lists the commits that have been reverse-patched 

C’è un modo migliore per farlo?

Crea un nuovo ramo, rebase il ramo in modo interattivo e rilascia i commit che non vuoi, quindi uniscilo.

Non puoi prendere cambiamenti fuori dal centro di un ramo senza rilanciare, ma la cosa giusta accadrà quando vedrà le stesse modifiche in una fusione successiva (ad esempio da cherry-picking e what-not).

Ho trovato una soluzione che funziona per me nel libro Pro Git .

Diciamo che vuoi escludere il file config.php .

Sul ramo A:

  1. Crea un file chiamato .gitattributes nella stessa dir, con questa riga: config.php merge=ours . Questo dice git quale strategia usare quando si unisce il file. In questo caso mantiene sempre la tua versione, es. la versione sul ramo in cui ti stai fondendo.

  2. Aggiungi il file .gitattributes e commetti

Sul ramo B: ripetere i passaggi 1-2

Prova a unire ora. Il tuo file dovrebbe essere lasciato inalterato.

Se hai un ramo di supporto in cui correggi bug e costruisci nuove versioni. Su master hai la prossima versione in cui crei anche nuove versioni frequentemente.

Ogni volta che si crea una nuova versione, si modifica la versione in qualche file, si esegue il commit del nuovo file, si crea un tag e si spinge. Ora le fusioni dal supporto al master avranno sempre conflitti nel file contenente le informazioni sulla versione.

Se il file contenente le informazioni sulla versione contiene solo le informazioni sulla versione, puoi andare con la risposta di fcurella. Ma se effettivamente può contenere anche informazioni fusibili (pom.xml, gradle.properties, MANIFEST.MF, …), è necessario eseguire qualche azione aggiuntiva.

Usiamo il seguente esempio

  C---D*---E---F* support / A---B---G---H*---I master 

dove i commit con le stelle contengono solo le modifiche dovute alle modifiche alla versione che dovrebbero essere ignorate durante l’unione.

Per unire il supporto al master senza conflitti di merge dovuti alle build della versione, puoi procedere in uno dei seguenti modi:

L’unione multipla si impegna

 git checkout master git merge C git merge D -s ours git merge E git merge F -s ours 

Con l’argomento -s ours stiamo dicendo a git di registrare solo un’unione senza alterare lo spazio di lavoro. Questo è paragonabile --record-only di svn .

Quanto sopra comporterà il seguente layout

  -------------C---D*---E---F* support / \ \ \ \ A---B---G---H*---I---J---K----L---M master 

Un commit di unione con cherry-pick

 git checkout master git merge support -s ours --no-commit git cherry-pick CE --no-commit git commit -m 'merged support into master' 

per prima cosa stiamo iniziando un’unione, ma registriamo solo che stiamo unendo, senza alterare lo spazio di lavoro e senza eseguire il commit di unione. Quindi stiamo selezionando a raccolta i commit, ancora senza commit. Alla fine stiamo impegnando l’unione.

Quanto sopra comporterà il seguente layout

  C---D*---E---F* support / \ A---B---G---H*---I---J master 

Si potrebbe persino automatizzare la raccolta delle ciliegie.

 git checkout master git merge support -s ours --no-commit for id in `git log support --reverse --not HEAD --format="%H [%an] %s" | grep -v "bump version" | sed "s/\(\w*\)\s.*/\1/g"` do git cherry-pick --no-commit $id done git commit -m 'merged support into master' 

Il motivo per cui questo non può essere fatto direttamente è che ogni commit contiene collegamenti al commit padre (in genere solo uno, ma diversi per le unioni). In questo modo se hai un solo commit (per la sum SHA1) viene fissata anche l’intera storia poiché i genitori contengono anche link ai loro genitori e così via. Quindi l’unico modo per tralasciare le patch nella cronologia è di scriverne uno nuovo. git rebase -i su un ramo appena creato è probabilmente il modo più semplice per ottenerlo.

È anche ansible modificare il file .git / info / attributes e tenerlo all’interno della cartella .git invece di aggiungere file .gitattribute dappertutto che richiederà eventualmente l’aggiunta al controllo del codice sorgente.

La domanda principale è: come vuoi rappresentare i commit che vuoi saltare?

  1. nasconderli furtivamente (non il mio preferito)
  2. saltarli esplicitamente
  3. annullarli esplicitamente

Sfortunatamente no. 2 è imansible da esprimere nel grafico della storia.

No. 1 è ansible, ma non lo farei mai : un commit di unione può contenere modifiche. – Normalmente un commit di merge punta al risultato dell’unione di altri due rami: tutte le cose sviluppate in quei rami dovrebbero essere nel codice dopo l’unione (cioè nel codice indicato dal commit di unione). E nient’altro dovrebbe essere in questo impegno.

Ma sorpresa, sorpresa, puoi cambiare l’intero codice base e rappresentarlo come unione. L’effetto di un’unione è duplice: unisce l’albero della cronologia e dovrebbe unire due basi di codice. Il primo lo fa di sicuro (altrimenti nessuno lo chiama fusione), per il secondo potrebbe fallire, ad esempio quando si verifica un conflitto di merge ed è stato risolto in modo errato (quindi le basi di codice non sono state unite correttamente).

Alcune delle altre risposte suggeriscono questo nascondimento. Raccomando il modo esplicito: unire più ripristinare i commit.

Se si desidera solo escludere alcune commit alla fine, è sufficiente eseguire il commit su un numero di commit specifico:

 git checkout partlyMergedFrom git whatchanged --> find the commit hash up to where you want to merge git checkout partlyMergedInto git merge e40a0e384f58409fe3c864c655a8d252b6422bfc git whatchanged --> check that you really got all the changes you want to have