git: salta specifici commit durante la fusione

Ho usato Git per circa un anno e penso che sia fantastico, ma ho appena iniziato una seconda versione del progetto e ho iniziato una nuova filiale per questo. Sto lottando un po ‘con il modo migliore per gestire le cose andando avanti.

Ho due rami chiamati say master10 (per v1) e master20 (per v2). Ho fatto correzioni di bug in v1 su branch master10 e ho sviluppato nuove cose su master20. Ogni volta che faccio un bug fix lo git merge master10 in v2 verificando master20 e facendo git merge master10 . Fin qui tutto bene.

Ora, tuttavia, ho apportato una modifica alla v1 che non desidero nella v2, ma voglio continuare a unire altre correzioni di bug. Come faccio a dire a Git di saltare quel particolare commit (o un intervallo di commit), ma che andando avanti vorrei ancora unire altre correzioni di bug.

Pensavo che git rebase potesse essere quello di cui avevo bisogno, ma ho letto il documento e la mia testa è quasi esplosa.

Penso che quello che voglio sia qualcosa come un comando “git sync” che dice a git che due rami sono ora in-sync e in futuro si fondono solo i commit da questo punto di sincronizzazione.

Qualsiasi aiuto apprezzato.

Se si desidera unire la maggior parte, ma non tutte le commit sul ramo “maint” a “master”, ad esempio, è ansible farlo. Richiede un po ‘di lavoro —- come accennato in precedenza, il solito caso d’uso è quello di unire tutto da un ramo — ma a volte capita che tu abbia apportato una modifica a una versione di rilascio che non dovrebbe essere integrata di nuovo (forse quella del codice stato sostituito in master già), quindi come lo si rappresenta? Ecco qui…

Supponiamo quindi che a maint siano state applicate 5 modifiche e che uno di questi (maint ~ 3) non debba essere riunito in master, sebbene tutti gli altri dovrebbero esserlo. Lo fai in tre fasi: in realtà unisci tutto prima di quello, dì a git di contrassegnare maint ~ 3 come fuso anche quando non lo è, e quindi unisci il resto. La magia è:

 bash $ git merge maint~4 bash $ git merge -s ours maint~3 bash $ git merge maint 

Il primo comando unisce tutto prima che il maint fastidioso si impegni sul master. Il messaggio di log di merge predefinito spiegherà che stai unendo “branch ‘maint’ (parte iniziale)”.

Il secondo comando unisce il fastidioso maint ~ 3 commit, ma l’opzione “-s ours” dice a git di usare una speciale “strategia di fusione” che, di fatto, funziona semplicemente mantenendo l’albero in cui vi state fondendo e ignorando i commit ) ti stai unendo completamente. Ma fa ancora un nuovo commit di unione con HEAD e maint ~ 3 come genitori, quindi il grafico di revisione ora dice che maint ~ 3 viene unito. Quindi, in effetti, probabilmente vorrai usare anche l’opzione -m per ‘git merge’, per spiegare che quel commit di maint ~ 3 viene effettivamente ignorato!

Il comando finale unisce semplicemente il resto di maint (maint ~ 2..maint) in master in modo da sincronizzarlo di nuovo.

IMHO, la cosa più logica da fare, è unire tutto, e quindi usare git revert (commit_you_dont_want) per rimuoverlo .

Esempio:

 git merge master git revert 12345678 

Se hai più commit “da ignorare”, o desideri modificare il messaggio di ripristino:

 git merge master git revert -n 123456 git revert -n abcdef git commit -m "... Except commits 123456 and abcdef" 

Quindi la tua cronologia potrebbe essere simile a:

 | ... Except 123456 and abcdef |\ Merge branch 'master' into 'your_branch' 

Se si verificano conflitti che implicano SOLO questi commit “da ignorare”, è ansible utilizzare:

 git merge master -X ours 

Quindi la tua versione persisterà sull’altra. Anche senza i messaggi di errore, puoi ancora “annullare” quei commit indesiderati, perché potrebbero avere altre modifiche che non sono in conflitto e non le vuoi ancora.

Se hai conflitti che coinvolgono NON SOLO i commit “da ignorare”, dovresti risolverli manualmente, e probabilmente dovrai risolverli nuovamente durante il ripristino.

I commit includono ascendenza. Non è ansible unire un commit senza unire precedenti commit.

Puoi selezionarli, naturalmente. È un stream sottile quando si ha un ramo in modalità manutenzione.

Una sorta di pubblicità per il mio progetto che fondamentalmente avvolge il processo descritto da @araqnid.

È una sorta di aiuto che introduce il seguente stream GIT:

  • c’è una notifica giornaliera / settimanale sulle fusioni in sospeso dalle filiali di manutenzione nel ramo dev / master
  • il mantenitore del ramo controlla lo stato e decide se è necessario eseguire tutti i commit e bloccarli o chiedere agli sviluppatori di bloccarsi. Alla fine, il ramo di manutenzione viene unito a upsteam.

Una citazione dalla pagina del progetto:

A seconda del stream di lavoro è ansible avere filiali di manutenzione o specifiche del cliente insieme al ramo principale. Questi rami sono anche chiamati rami LTS.

Spesso gli hot fix vanno nei rami in cui è stato segnalato il bug e quindi il commit viene unito nuovamente al ramo principale.

La pratica generale è di avere tutti i rami perfettamente sincronizzati con il master, cioè si desidera vedere un delta chiaro tra un particolare ramo e master per capire se il master contiene tutte le funzionalità e le correzioni dei bug.

Tuttavia a volte non si desiderano particolari commit perché sono specifici del cliente e non devono essere visibili da altri utenti. Oppure il tuo master branch è stato così diverso da richiedere un approccio completamente diverso per risolvere il problema, o ancora meglio, il problema non è più presente.

Inoltre, in caso di cherry-pick dal master nel branch di manutenzione, il commit risultante deve essere bloccato nel master.

Sembra un caso classico per ‘git cherry-pick’ https://git-scm.com/docs/git-cherry-pick fa esattamente quello che sembra

Crea un terzo ramo per le modifiche che desideri in master10 ma non in master20. Considera sempre master10 come il tuo “maestro”, il ramo più stabile di tutti. Il ramo che tutti gli altri rami vogliono mantenere sempre sincronizzati.