Até agora, a parte mais confusa do git está sendo rebaseada para outro ramo. Especificamente, são os argumentos da linha de comando que são confusos.
Cada vez que quero refazer um pequeno pedaço de uma ramificação na ponta de outra, preciso revisar a documentação do git rebase e levo de 5 a 10 minutos para entender quais devem ser os três argumentos principais.
git rebase <upstream> <branch> --onto <newbase>
Qual é uma boa regra geral para me ajudar a memorizar como cada um desses três parâmetros deve ser definido, considerando qualquer tipo de rebase em outro ramo?
Lembre-se de que revi a documentação do git-rebase de novo, e de novo, e de novo, e de novo (e de novo), mas sempre é difícil de entender (como um white paper científico chato ou algo assim). Então, neste ponto, sinto que preciso envolver outras pessoas para me ajudar a entender.
Meu objetivo é que eu nunca precise revisar a documentação desses parâmetros básicos. Não pude memorizá-los até agora, e já fiz muitas repercussões. Portanto, é um pouco incomum que eu tenha sido capaz de memorizar todos os outros comandos e seus parâmetros até agora, mas não me refazendo --onto
.
Respostas:
Vamos pular
--onto
por um momento.upstream
ebranch
são bem básicos e, na verdade, meio que imitamcheckout
ebranch
- o segundo argumento é opcional:(Com exceção, os nomes desses argumentos
rebase
, "a montante" e "filial" não são muito descritivo IMO I tipicamente pensar neles como peachoftree,.<start>
E<end>
, que é como eu vou estar usando-os:git rebase <start> <end>
)Quando o segundo ramo é omitido, o resultado é quase o mesmo que primeiro fazer check-out desse ramo e, em seguida, fazê-lo como se você não tivesse especificado esse ramo. A exceção é
branch
que não altera sua ramificação atual:Quanto a entender o que
rebase
faz quando invocado, comecei pensando nele como um tipo especial de mesclagem. Não é verdade, mas ajudou quando começou a entender o rebase. Para emprestar o exemplo de peachoftree:A
git merge master
resulta nisso:Enquanto a
git rebase master
(enquanto estiver no ramofeature
!) Resulta nisso:Nos dois casos,
feature
agora contém código de ambosmaster
efeature
. Se você não estiver ativofeature
, o segundo argumento pode ser usado para alternar para ele como um atalho:git rebase master feature
fará o mesmo que acima.Agora, para o especial
--onto
. A parte importante a ser lembrada é que o padrão é<start>
se não for especificado. Então, acima, se eu especificasse--onto
especificamente, isso resultaria no mesmo:(Eu não uso
--onto
sem especificar<end>
simplesmente porque é mais fácil analisar mentalmente, mesmo que esses dois sejam iguais se já estiverem ativadosfeature
.)Para ver por que
--onto
é útil, aqui está um exemplo diferente. Digamos que eu estava ligadofeature
e notei um bug, que eu comecei a consertar - mas havia ramificado emfeature
vez demaster
por engano:O que eu quero é "mover" esses commits para
bugfix
que eles não sejam mais dependentesfeature
. Como é, qualquer tipo de mesclagem ou rebase mostrada acima nesta resposta levará os trêsfeature
commits junto com os doisbugfix
commits.Por exemplo,
git rebase master bugfix
está errado. Ocorre<start>
que o intervalo<end>
inclui todos os commits defeature
, que são reproduzidos em cima demaster
:O que nós queremos realmente é o intervalo de commits de
feature
quebugfix
para ser repetido em cimamaster
. É--onto
para isso - especificar um destino de "repetição" diferente do ramo "iniciar":git rebase --onto master feature bugfix
fonte
Apenas uma atualização, o rebasing é principalmente para quando você deseja que seu histórico de consolidação pareça linear se dois ramos se desenvolverem independentemente um do outro, basicamente ele reescreve o histórico de consolidação.
do jeito que eu gosto de fazer é
git rebase --onto <target branch> <start branch> <end branch>
onde
<target branch>
é a ramificação na qual você está reestruturando,<start branch>
normalmente é a ramificação da qual se<end branch>
divide e<end branch>
é a ramificação na qual você está reestruturando.se você começar com
e fazer
você vai ter
Outra coisa boa a saber é que o
<target branch>
padrão é que<start branch>
você possa fazer o mesmo rebase quese precisar de mais ajuda, consulte o guia Rebase sem lágrimas
fonte
master
próprio ramo inalterado. Você apenas obtém 'recurso' para ramificar comoG--C'--D'--E'
enquantomaster
ainda pára emG
.<target branch>
e como<start branch>
são diferentes para ajudar os leitores a entender o caso mais geral?