Come faccio a "sovrascrivere", anziché "unire", un ramo su un altro ramo in Git?


257

Ho due rami emaile staging. stagingè l'ultimo e non ho più bisogno delle vecchie modifiche nel emailramo, ma non voglio cancellarle.

Quindi voglio solo scaricare tutto il contenuto stagingin emailmodo che entrambi puntino allo stesso commit. È possibile?


Risposte:


196

Puoi utilizzare la strategia di unione "nostra":

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head

26
Ho provato questo, e mi sembra al contrario? Questo non scarica il contenuto dell'email nella messa in scena e non viceversa?
— Max

27
@Max ho avuto la stessa confusione e questo mi ha causato molti problemi. È necessario eseguire questo comando dal ramo più recente (gestione temporanea), quindi eseguire un'unione / PR normale con il ramo precedente (e-mail).
— MrGlass,

7
Perché ;alla fine di ogni comando? Ho fatto senza ;e sembra funzionare. Anche questa risposta è incompleta, il terzo passo è quello di verificare il vecchio ramo (e-mail) e quindi unire nuovamente la gestione temporanea.
— Rosdi Kasim,

4
git rebase -s theirs <oldbranc> <newbranch> funziona anche (non importa quale ramo sei). Si noti che in rebase "loro" è in realtà il newbranch perché "nostro" è il capo a cui stiamo attualmente applicando i commit.
— Rolf,

4
@Rolf: ma rebase si sbarazzerà delle informazioni di unione e appiattisce la storia. Non necessariamente quello che stai cercando. Inoltre, non è una buona idea, se stai lavorando con una storia già pubblicata.
— Knittl

99

Se vuoi solo che i due rami "email" e "staging" siano uguali, puoi taggare il ramo "email", quindi ripristinare il ramo "email" su quello "staging":

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

Puoi anche rifare il ramo "staging" sul ramo "email". Ma il risultato conterrà la modifica dei due rami.


1
probabilmente intendi git checkout, git checknon esiste per quanto ne
— so

4
Hai ragione, sono così abituato a completare il comando git che scrivo sempre "git check <TAB>" per scrivere "git checkout"! Corretto.
— Sylvain Defresne,

17
git reset interrompe il repository di altre persone che hanno clonato il tuo repository
— Geoffrey De Smet,

Credo che questa sia la risposta giusta. emailla testa del ramo dovrebbe semplicemente indicare lo stesso capo staginged entrambi avranno gli stessi impegni, la stessa storia.
— cicerocamargo,

76

Ho visto diverse risposte e questa è l'unica procedura che mi ha permesso di risolverlo senza alcun conflitto.

Se vuoi tutte le modifiche da branch_new in branch_old, allora:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

una volta applicati quei quattro comandi è possibile inviare branch_old senza alcun problema


5
La tua risposta si adatta davvero meglio al mio problema in quanto non volevo ripristinare HEAD, dichiarare una preferenza per i file più recenti nel ramo più recente quando si uniscono le cose a quello precedente e ha funzionato senza problemi! +1
— stufe

Ho spinto il mio branch_new a distanza dopo la "nostra unione", e questo metodo ha funzionato per me. È stato necessario per me spingere? O avrebbe funzionato senza? (Non ero sicuro che avrebbe usato il ramo locale o remoto). Grazie!
— aspergillusOryzae

Perché non puoi semplicemente fare quanto segue? git checkout branch_old git merge -s loro Clue branch_new tratto da stackoverflow.com/questions/14275856/...
— Ripu Daman

Dice che non è stato possibile trovare la strategia di unione "loro".
— arango_86,

Funziona perfettamente per me, ha il vantaggio di non reimpostare nulla
— Romain,

68

Le altre risposte mi davano gli indizi giusti, ma non mi aiutarono completamente.

Ecco cosa ha funzionato per me:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

Senza il quarto passo della fusione con la nostra strategia, la spinta è considerata un aggiornamento non veloce e verrà respinta (da GitHub).


Ciò rende errato il messaggio di merge-commit, ma sì, funziona benissimo.
— cdunn2001,

cdunn2001, sono curioso. Qual era il messaggio di merge-commit che ti aspettavi e come è stato incasinato questo?
— Shyam Habarakada,

Dice "Unisci il ramo di tracciamento remoto" origine / e-mail "in e-mail". Non menziona la messa in scena. Nessun grosso problema però. Basta modificare il commit o utilizzare merge -m 'This is not my beautiful house.' -s ours origin/email.
— cdunn2001,

@ShyamHabarakada, faccio come dici tu e ho il problema dell'aggiornamento non veloce. perché non succede nulla quando faccio il 4 ° passaggio.
— kommradHomer dal

Il quarto passaggio richiede l'utilizzo di origine / e-mail, non funziona solo con la posta elettronica locale.
— Travis Reeder,

45

Se sei come me e non vuoi avere a che fare con l'unione, puoi fare i passaggi precedenti, tranne usare la forza invece di unire, perché creerà una traccia distruttiva della carta di registro:

git checkout email
git reset --hard staging
git push origin email --force

Nota: questo è solo se davvero non vuoi più vedere le cose nell'e-mail.


1
git push origin email: force non ha funzionato per me poiché Step2 ha lasciato i rami divergenti. Quindi dopo Step2, questo è quello che ho fatto: git resetta origin / email e poi git push
— user3505394

2
Questo è esattamente ciò che è stato chiesto in questione: "come sovrascrivere anziché unire". Dovrebbe essere accettata la risposta.
— Jozols,

17

Volevo unire due rami in modo che tutti i contenuti old_branchvenissero aggiornati con i contenuti dinew_branch

Per me questo ha funzionato come un fascino:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch

10

Che ne dite di:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease

@emptywalls perché fa un push forzato senza avvisare l'utente che può essere rifiutato dal server, né spiega perché sia ​​necessario. Detto questo, è un'opzione praticabile per un progetto per uno sviluppatore
— David Costa,

@DavidCosta perché questo dovrebbe essere rifiutato dal server? questo è un semplice ramo di posta elettronica da eliminare e copiare la stadiazione su e-mail '... Quindi voglio solo scaricare tutto il contenuto di' stadiazione 'in' e-mail 'in modo che entrambi puntino allo stesso commit' - questo è esattamente ciò che sta accadendo Qui.
— Arek S,

@ArekS può essere rifiutato da un hook lato server se il ramo è impostato come "protetto", ad esempio in GitLab. Il problema è che se qualcun altro ha derivato il suo ramo dall'e-mail prima di questa operazione e poi cerca di spingere, i riferimenti non corrispondono più (perché alcuni commettono semplicemente svaniti)
— David Costa,

1
Ho modificato l'originale da --force a --force-with-lease, che fa il trucco in modo non distruttivo.
— frandroid,

1
Questo è il modo migliore se vuoi semplicemente spazzare via un ramo e avviarlo pulito dal ramo di origine.
— Shane,

6

Altre risposte sembravano incomplete.
Ho provato di seguito per intero, e ha funzionato bene.

NOTA:
1. Creare una copia del repository prima di provare di seguito, per essere al sicuro.

Dettagli:
1. Tutto lo sviluppo avviene nel ramo dev
2. Il ramo qa è solo la stessa copia di dev
3. Di volta in volta, il codice dev deve essere spostato / sovrascritto nel ramo qa

quindi dobbiamo sovrascrivere il ramo qa, dal ramo dev

Parte 1:
Con i comandi seguenti, il vecchio qa è stato aggiornato al nuovo sviluppatore:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

Di seguito il commento automatico per l'ultima push:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

Questo commento sembra al contrario, perché anche la sequenza sopra sembra al contrario

Parte 2:

Di seguito sono inaspettati, nuovi impegni locali in sviluppo, quelli inutili,
quindi, dobbiamo buttare via e rendere il dev non toccato.

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

Parte 3:
verifica che tutto sia come previsto:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

È tutto.
1. il vecchio qa è ora sovrascritto dal nuovo codice di filiale dev
2. local è pulito (origine / dev remota non è toccata)


6

Il modo più semplice per farlo:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

Ora il ramo e-mail e la gestione temporanea sono gli stessi.


2
Avviso: questo cancella tutti gli commit sul emailramo. È come cancellare il emailramo e crearlo di nuovo in testa al stagingramo.
— Cameron Hudson,

2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging

1
Questa risposta mi sarebbe stata più chiara se il commento fosse stato separato dal commento di fusione nel comando. Spiega brevemente cosa fa -X e come influenza questa fusione. Grazie comunque. Mi ha fatto cercare :)
— Noelicus,

@noelicus grazie per il commento e hai ragione. Potrei modificare la risposta in futuro.
— Willa,

0

Questo non altera il ramo più recente originale e ti dà la possibilità di apportare ulteriori modifiche prima del commit finale.

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.