Trasforma il ramo Git corrente in un ramo principale


1657

Ho un repository in Git. Ho creato un ramo, quindi ho apportato alcune modifiche sia al master che al ramo.

Poi, decine di commit più tardi, ho capito che il ramo è in uno stato molto migliore rispetto al master, quindi voglio che il ramo "diventi" il master e ignori le modifiche sul master.

Non riesco a unirlo, perché non voglio mantenere le modifiche sul master. Cosa dovrei fare?

Extra : in questo caso, il "vecchio" master è già stato pushtrasferito su un altro repository come GitHub. In che modo questo cambia le cose?


2
Controllare risposte alla domanda molto simile stackoverflow.com/q/2862590/151641
mloskot

4
Aveva un medesimo problema, ma ho semplicemente tolto il master e rinominato un altro ramo da padroneggiare: stackoverflow.com/a/14518201/189673
jayarjo

10
@jayarjo dovresti evitarlo, se possibile, perché riscriverà la storia e causerà problemi a tutti gli altri quando tenteranno di estrarre il master.
joelittlejohn,

3
Questo è il motivo per cui amo la risposta di @Jefromi. Non è in corso alcuna decostruzione della storia dell'archivio.
froggythefrog,

Risposte:


2134

Il problema con le altre due risposte è che il nuovo maestro non ha il vecchio maestro come antenato, quindi quando lo spingi, tutti gli altri verranno incasinati. Questo è quello che vuoi fare:

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

Se vuoi che la tua cronologia sia un po 'più chiara, ti consiglio di aggiungere alcune informazioni al messaggio di commit unione per chiarire cosa hai fatto. Cambia la seconda riga in:

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message

25
Nota sulle "strategie" di unione di git: --strategy=oursè diverso da --strategy=recursive -Xours. Vale a dire "la nostra" può essere una strategia in sé (il risultato sarà il ramo corrente, non importa quale), o passato come opzione alla strategia "ricorsiva" (porta le modifiche di un altro ramo e preferisci automaticamente le modifiche del ramo corrente quando c'è un conflitto ).
Kelvin,

5
Ho dovuto fare la seconda riga git merge --strategy=ours master -m "new master"perché funzionasse.
incandescentman,

5
@Johsm Questo è esattamente ciò di cui parla la prima frase della mia risposta. Se lo fai, il nuovo master non avrà la stessa storia del vecchio master, il che è molto brutto se vuoi spingere / tirare. È necessario disporre di origini condivise affinché funzioni correttamente; se invece fai quello che stai dicendo, allora quando provi a spingerlo semplicemente fallirà a meno che non lo forzi (perché questo è cattivo e sta cercando di fermarti), e se lo fai forzatamente, allora chiunque tira tenterà di unire il vecchio maestro e il nuovo maestro, che probabilmente sarà un disastro ferroviario.
Cascabel,

4
Se viene visualizzato l'editor vi durante l'unione, digitare: w (per salvare): q (per uscire da vi)
Tomas Kubes,

9
Questa risposta funziona alla grande. Volevo solo aggiungere (per le persone che potrebbero essere nuove o insicure) che dovrai fare git pushsubito dopo questo se vuoi che il tuo codice venga trasferito sul telecomando. È possibile che Your branch is ahead of 'origin/master' by 50 commits.venga visualizzato un avviso come Questo è previsto. Basta spingerlo! : D
chapeljuice,

388

Assicurati che tutto sia archiviato nel tuo repository remoto (GitHub):

git checkout master

Sovrascrivi "master" con "better_branch":

git reset --hard better_branch

Forzare la spinta al repository remoto:

git push -f origin master

81
Questa è probabilmente la risposta che molte persone stanno cercando. Tutte le altre risposte con l'unione della strategia BS non sostituiscono del tutto il ramo. Questo ha reso tutto come volevo, semplicemente sovrascrivendo il ramo e spingendolo verso l'alto.
Gubatron,

31
anche se questo è davvero ciò che molti stanno cercando, va notato che qualsiasi altra copia locale del repository dovrà essere la git reset --hard origin/masterprossima volta che vorranno estrarre, altrimenti git proverà a unire le modifiche nel loro (ora) divergente locale. I pericoli di questo sono spiegati di più in questa risposta
7yl4r

3
si noti inoltre che è necessario essere autorizzati a forzare la spinta al repository - ad esempio in un ambiente aziendale che non funzionerà
inetphantom

Il lato positivo qui può anche essere un aspetto negativo a seconda di ciò che la gente vuole. Se vuoi andare fino a sostituire la storia del maestro con la storia dell'altro ramo, questa è la tua risposta.
b15,

75

Modifica: non hai detto di essere passato a un repository pubblico! Questo fa la differenza.

Ci sono due modi, il modo "sporco" e il modo "pulito". Supponiamo che il tuo ramo sia chiamato new-master. Questo è il modo pulito:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

Ciò farà cambiare i file di configurazione in modo che corrispondano ai rami rinominati.

Puoi anche farlo nel modo sporco, che non aggiorna i file di configurazione. Questo è un po 'quello che succede sotto il cofano di quanto sopra ...

mv -i .git/refs/new-master .git/refs/master
git checkout master

2
Grazie. Un'altra domanda. Lo sto spingendo su Github. Cosa succederà lì, se lo faccio?
Karel Bílek,

3
@Karel: creerà un po 'di confusione per gli altri utenti; dovranno reimpostare il proprio master sul master github. Se vuoi evitare di causare loro problemi, dai un'occhiata alla mia risposta.
Cascabel,

6
@Dietrick Epp: non sono sicuro che sia una buona idea anche suggerire il modo sporco. Confonderà il monitoraggio remoto, i reflog ... non riesco a pensare a nessun motivo per cui l'avresti mai fatto.
Cascabel,

2
Ah, questo è un buon punto. Si può avere entrambe le cose, però: git branch old-master master; git branch -f master new-master. Crea un nuovo ramo di backup, quindi sposta direttamente il master su new-master. (E mi dispiace per aver sbagliato a scrivere il tuo nome, l'ho appena notato)
Cascabel,

2
@FakeName Non ho concluso che non c'era motivo di farlo, solo che non c'è motivo di farlo nel modo sporco . Puoi farlo usando i normali comandi (come nel mio commento precedente) e ottenere lo stesso risultato, tranne con i reflog intatti e nessuna possibilità di borking cose. Ed è garantito che funzioni, dal momento che non stai confondendo con i dettagli di implementazione.
Cascabel,

46

Rinomina il ramo in masterda:

git branch -M branch_name master

11
Sfortunatamente git non tiene traccia delle rinominazioni dei rami, quindi se hai già trasferito il tuo repository su un telecomando e altri hanno cambiamenti locali sul loro vecchio ramo principale locale, saranno nei guai.
thSoft

c'è una differenza tra questo e git checkout master&&git reset --hard better_branch?
wotanii,

26

Da quello che ho capito, puoi ramificare il ramo corrente in un ramo esistente. In sostanza, questo sovrascriverà mastercon qualsiasi cosa tu abbia nel ramo corrente:

git branch -f master HEAD

Una volta che lo hai fatto, puoi normalmente spingere il tuo masterramo locale , eventualmente richiedendo anche qui il parametro force :

git push -f origin master

Nessuna fusione, nessun comando lungo. Semplicemente branche push- ma sì, questo riscriverà la storia del masterramo, quindi se lavori in una squadra devi sapere cosa stai facendo.




In alternativa, ho scoperto che è possibile inviare qualsiasi ramo a qualsiasi ramo remoto, quindi:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master

Molto semplice e ha funzionato perfettamente! Due comandi git semplici e facili da capire. Il mio repository git è stato salvato e ora sembra super pulito. Grazie!
thehelix,

16

Ho trovato la risposta che cercavo nel post del blog Sostituisci il ramo principale con un altro ramo in git :

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

È essenzialmente la stessa della risposta di Cascabel . Tranne che l '"opzione" che ha aggiunto sotto la sua soluzione è già integrata nel mio blocco di codice principale.

È più facile da trovare in questo modo.

Sto aggiungendo questa come una nuova risposta, perché se avrò bisogno di questa soluzione in un secondo momento, voglio avere tutto il codice che userò in un blocco di codice.

In caso contrario, posso copiare e incollare, quindi leggere i dettagli qui sotto per vedere la linea che ho dovuto cambiato - dopo che ho già giustiziato esso.


14

Le soluzioni fornite qui (rinominando il ramo in "master") non insistono sulle conseguenze per il repository remoto (GitHub):

    -f
    --vigore

Di solito, il comando rifiuta di aggiornare un riferimento remoto che non è un antenato del riferimento locale utilizzato per sovrascriverlo. Questo flag disabilita il controllo. Ciò può causare la perdita di commit del repository remoto; usalo con cura.

Se altri hanno già creato il tuo repository, non saranno in grado di estrarre la nuova cronologia master senza sostituire il proprio master con quel nuovo ramo master GitHub (o gestire un sacco di fusioni).
Esistono alternative a un git push - force per repository pubblici .
La risposta di Jefromi (che unisce le modifiche giuste al master originale) è una di queste.


14

Ho trovato questo metodo semplice per funzionare al meglio. Non riscrive la cronologia e tutti i check-in precedenti della filiale verranno aggiunti al master. Nulla viene perso e puoi vedere chiaramente cosa è successo nel registro di commit.

Obiettivo: rendere lo stato corrente di "ramo" il "master"

Lavorando su una filiale, esegui il commit e invia le modifiche per assicurarti che i repository locali e remoti siano aggiornati:

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

Successivamente, il master sarà lo stato esatto dell'ultimo commit del ramo e il log del commit principale mostrerà tutti i check-in del ramo.


10

Si può anche fare il checkout di tutti i file dall'altro ramo nel master:

git checkout master
git checkout better_branch -- .

e quindi eseguire il commit di tutte le modifiche.


5

Per aggiungere alla risposta di Jefromi, se non si desidera inserire un'unione senza significato nella storia del sourceramo, è possibile creare un ramo temporaneo per l' oursunione, quindi eliminarlo:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

In questo modo il commit della fusione esisterà solo nella storia di target ramo.

In alternativa, se non si desidera creare affatto un'unione, è possibile semplicemente acquisire i contenuti sourcee utilizzarli per un nuovo commit su target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>

3

Per me, volevo che il mio devl tornasse dal maestro dopo che era avanti.

Durante lo sviluppo:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f

2

Il mio modo di fare le cose è il seguente

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop

2

Se stai usando eGit in Eclipse :

  • Fare clic con il tasto destro sul nodo del progetto.
  • Scegli Team → quindi Avanzate → quindi Rinomina ramo
  • Quindi espandere la cartella di tracciamento remoto .
  • Scegli il ramo con il nome sbagliato, quindi fai clic sul pulsante Rinomina, rinominalo in qualsiasi nome nuovo.
  • Scegli il nuovo master, quindi rinominalo in master.

L'ho fatto ma non sono sicuro che abbia funzionato. Su github, nulla è cambiato ma sulle estensioni git posso vedere che il ramo è stato rinominato.
Pramod

0

I seguenti passaggi vengono eseguiti nel browser Git basato su Atlassian (server Bitbucket)

Rendere {current-branch} come master

  1. Crea un ramo mastere chiamalo "duplicato principale".
  2. Crea un ramo da {current-branch} e chiamalo "{current-branch} -copy".
  3. Nell'impostazione del repository (Bitbucket) cambia "Default Branch" per puntare a "master-duplicato" (senza questo passaggio, non sarai in grado di eliminare il master - "Nel passaggio successivo").
  4. Elimina il ramo "master" - ho fatto questo passaggio dall'albero dei sorgenti (puoi farlo dalla CLI o dal browser Git)
  5. Rinominare "{ramo corrente}" in "master" e spingere nel repository (questo creerà un nuovo ramo "master", ma esiste ancora "{ramo corrente}").
  6. Nelle impostazioni del repository, modificare "Predefinito Branch" per puntare a "master".
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.