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.