Cambia la base del ramo


145

Ho un albero come questo:

(commit 1) - master
                \-- (commit 2) - (commit 3) - demo
                                                \-- (commit 4) - (commit 5) - PRO

e devo spostare il ramo PRO su master

(commit 1) - master
                |-- (commit 2) - (commit 3) - demo
                \-- (commit 4) - (commit 5) - PRO

Ho provato un git rebase masterramo PRO, ma non succede nulla.

Per chiarire : stavo lavorando in master e poi ho dovuto fare una demo del prodotto ( git checkout -b demoe alcuni commit). Quindi, per errore, creo un altro ramo dalla demo ( git checkout -b PROe alcuni commit) e ora ho bisogno di spostare il ramo PRO per padroneggiare e lasciare intatta la demo. Alla fine, sia la demo che il PRO si bloccheranno dal master.


Risposte:


281

Utilizzare --ontoper quello:

git rebase --onto newBase oldBase feature/branch

Dato il tuo caso:

git checkout PRO # Just to be clear which branch to be on.
git rebase --onto master demo PRO

Fondamentalmente, prendi tutti i commit da dopo demofino a PRO, e li rimetti in mastercommit.


È anche la strada da percorrere se la situazione è l'opposto? == Ho verificato -b dal master il secondo ramo, ma volevo farlo dal primo. Quindi l'ho fatto git rebase --onto first-branch second-branch second-branchma non capisco la sintassi
Fla

1
@Fla in quel caso, sarebbegit rebase --onto first-branch master second-branch
nVitius

9
Ho letto questo manuale su --onto, e il modo in cui mi ha scritto aiutatogit rebase --onto newBase oldBase feature/branch
Gabe

@PhilipRego Questo non è corretto. origin/newBaseè il nome di un ramo, proprio come newBasenel mio esempio. Dipenderebbe solo se si sta eseguendo il reinserimento in un ramo esistente nel repository locale ( newBase) o in uno esistente sul telecomando ( origin/newBase).
loganfsmyth,

@PhilipRego Quelle non sono cose indipendenti. newBaseè il nome di un ramo locale ed origin/newBaseè il nome di un ramo remoto. Quale vuoi dipende da cosa ti stai rifacendo. Non è che uno funzioni e uno no, è che si rifanno a cose diverse. La domanda originale non menziona mai i telecomandi, quindi usare i telecomandi nel mio esempio non corrisponderebbe alla domanda che è stata posta.
loganfsmyth,

22

Cercherò di essere il più generico possibile. Innanzitutto, assicurati di essere sul ramo desiderato:

git checkout current-branch

Quindi utilizzare il comando seguente (dove si new-base-branchtrova il ramo che si desidera essere la nuova base, ed current-base-branchè il ramo che è la base corrente.)

git rebase --onto new-base-branch current-base-branch

Se non hai conflitti, allora fantastico: hai finito. Se lo fai (nella maggior parte dei casi), continua a leggere.

Potrebbero sorgere conflitti e dovrai risolverli manualmente. Git ora cerca di fare un "3-way merge" tra il vostro current-branch, current-base-branche new-base-branch. All'incirca questo è come git funzionerà internamente:

  1. Git prima rinnoverà la parte current-base-branchsuperiore di new-base-branch. Potrebbero esserci conflitti; che dovrai risolvere manualmente. Fatto ciò, di solito lo fai git add .e git rebase --continue. Creerà un nuovo commit temporaneo temp-commit-hashper questo.

  2. Dopo questo, Git sarà ora rebase tua current-branchalto su di temp-commit-hash. Potrebbero esserci ulteriori conflitti e di nuovo dovrai risolverli manualmente. Una volta fatto, si continua ancora con git add .e git rebase --continue, dopo di che si è ricalcolato con successo il vostro current-branchin cima alla new-base-branch.


Nota: se inizi a sbagliare, puoi farlo in git rebase --abortqualsiasi momento durante il processo di rebase e tornare al punto di partenza.


Il rebasecomando pubblicato mi dà solo "fatale: invalida 'ramo-base-corrente' non valido. Inoltre, perché è anche necessario dire a GIT qual è l'attuale ramo padre dell'attuale ramo - non dovrebbe saperlo già?
Matt Arnold,

21

Acquista nel PROramo, copia gli hash di commit più vecchi ( commit4 ) e più recenti ( commit5 ) di questo ramo e incollali altrove:

$ git checkout PRO
$ git log            # see the commit history
# copy the oldest & latest commit-hash 

Elimina il PROramo (conserva un backup solo per sicurezza). Crea e fai il checkout in una nuova PROfiliale da master:

$ git branch PRO.bac    # create a new branch PRO.bac = PRO as backup

$ git checkout master
$ git branch -D PRO     # delete the local PRO branch
$ git checkout -b PRO   # create and checkout to a new 'PRO' branch from 'master'

Prendi ( cherry-pick ) la gamma di commit del PROramo precedente nel nuovo PROramo:

$ git cherry-pick commit4^..commit5   # cherry-pick range of commits
# note the '^' after commit4

Ora, se tutto è ok, allora forza (-f) spingere verso il remote PROramo ed eliminare il PRO.bacramo locale :

$ git log                  # check the commit history

$ git push -f origin HEAD  # replace the remote PRO by local PRO branch history
# git branch -D PRO.bac    # delete local PRO.bac branch

1

Ho avuto un approccio leggermente diverso utilizzando reset e stash che evita di eliminare e ricreare i rami, nonché di eliminare la necessità di cambiare ramo:

$ git checkout PRO
$ git reset commit4 # This will set PROs HEAD to be at commit 4, and leave the modified commit 5 files in ur working index
$ git stash save -m "Commit message"
$ git reset commit 3
$ git stash save -m "Commit message"
$ git reset master --hard
$ git stash pop
$ git stash pop
$ git push --force # force if its already been push remotely

Reimpostando il ramo su un commit in base al commit, fondamentalmente semplicemente riavvolgi la cronologia dei rami un commit alla volta.


Dovresti rimuovere lo spazio tra "commit" e "3" sulla 4a riga?
Alexis Wilke,
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.