Alterar base da filial

145

Eu tenho uma árvore como esta:

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

e eu tenho que mover o ramo PRO para dominar

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

Eu tentei um git rebase masterramo PRO, mas nada acontece.

Para esclarecer : eu estava trabalhando em master e então tive que fazer uma demonstração do produto ( git checkout -b demoe algumas confirmações). Então, por engano, crio outro ramo a partir da demonstração ( git checkout -b PROe algumas confirmações) e agora preciso mover o ramo PRO para dominar e deixar a demonstração intacta. No final, tanto o demo quanto o PRO serão suspensos do master.

Ivan
fonte
possível duplicata do ponto de ramificação
Wladimir Palant

Respostas:

281

Use --ontopara isso:

git rebase --onto newBase oldBase feature/branch

Dado o seu caso:

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

Basicamente, você pega todas as confirmações de depois demoaté PROe as refaz para a masterconfirmação.

loganfsmyth
fonte
Esse também é o caminho a seguir se a situação for oposta? == Eu efetuei o check--b do master no segundo ramo, mas queria fazê-lo no primeiro. Então eu fiz git rebase --onto first-branch second-branch second-branch, mas eu não entendo a sintaxe
Fla
1
@Fla nesse caso, seriagit rebase --onto first-branch master second-branch
nVitius
9
Eu li este guia on --onto, e como eles escreveram me ajudougit rebase --onto newBase oldBase feature/branch
gabe
@PhilipRego Isso está incorreto. origin/newBaseé o nome de um ramo, assim como newBaseno meu exemplo. Depende apenas se você estiver reestruturando em um ramo que existe no seu repositório local ( newBase) ou em um que existe no controle remoto ( origin/newBase).
Loganfsmyth 17/09/19
@PhilipRego Essas não são coisas independentes. newBaseé o nome de uma filial local e origin/newBaseé o nome de uma filial remota. Qual deles você quer depende do que você está refazendo. Não é que se trabalhe e se não, é que eles se refazem em coisas diferentes. A pergunta original nunca menciona controles remotos, portanto, usar controles remotos no meu exemplo não corresponderia à pergunta que foi feita.
Loganfsmyth 18/09/19
22

Vou tentar ser o mais genérico possível. Primeiro, verifique se você está no ramo desejado:

git checkout current-branch

Em seguida, use o seguinte comando (onde new-base-branché o ramo que você deseja que seja sua nova base e current-base-branché o ramo que é sua base atual.)

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

Se você não tiver conflitos, então ótimo - está feito. Se sim (na maioria dos casos), continue lendo.

Podem surgir conflitos, e você terá que resolvê-los manualmente. O Git agora tenta fazer uma "fusão de três vias" entre você current-branch, current-base-branche new-base-branch. Aproximadamente é assim que o git funcionará internamente:

  1. O Git primeiro rebase o current-base-branchem cima do new-base-branch. Pode haver conflitos; que você terá que resolver manualmente. Depois disso, você costuma fazer git add .e git rebase --continue. Isso criará um novo commit temporário temp-commit-hashpara isso.

  2. Depois disso, o Git agora rebase o seu current-branchem cima de temp-commit-hash. Pode haver mais conflitos e, novamente, você terá que resolvê-los manualmente. Uma vez feito isso, você continuar novamente com o git add .e git rebase --continue, após o qual você rebased com sucesso o seu current-branchno topo do new-base-branch.


Nota: Se você começar a estragar tudo, poderá fazer a git rebase --abortqualquer momento durante o processo de rebase e voltar ao ponto de partida.

ARCA
fonte
O rebasecomando postado apenas me dá "fatal: upstream inválido 'current-base-branch'". Além disso, por que é necessário dizer ao GIT qual é o ramo pai atual do ramo atual - ele já não deveria saber disso?
Matt Arnold
21

Faça o checkout para PROramificar, copie os hashes de confirmação mais antigos ( commit4 ) e mais recentes ( commit5 ) deste ramo e cole em outro lugar:

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

Exclua a PROramificação (mantenha um backup apenas por segurança). Crie e efetue o checkout para uma nova PROfilial em 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'

Leve ( escolha de cereja ) o intervalo de confirmações da PROramificação anterior para a nova PROramificação:

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

Agora, se tudo estiver ok, force (-f) a pressionar para remote PROramificar e excluir a PRO.bacramificação local :

$ 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
Sajib Khan
fonte
1

Eu tive uma abordagem um pouco diferente usando redefinições e stashes que evitam excluir e recriar ramificações, além de eliminar a necessidade de alternar ramificações:

$ 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

Ao redefinir a ramificação em uma base de consolidação por consolidação, você basicamente apenas retrocede o histórico de ramificação, uma consolidação por vez.

madjase
fonte
Você deve remover o espaço entre "confirmar" e "3" na quarta linha?
Alexis Wilke