git rebase, acompanhando 'local' e 'remoto'

174

Ao fazer uma rebase do git, geralmente tenho dificuldade em descobrir o que está acontecendo com o 'local' e o 'remoto' ao resolver conflitos. Às vezes, tenho a impressão de que eles trocam de lado um compromisso para o outro.

Provavelmente é (definitivamente) porque ainda não entendi direito.

Ao rebasear, quem é 'local' e quem é 'remoto'?

(Eu uso o P4Merge para resolver conflitos)

Benjol
fonte
É possível que ler isso o ajude? O resto do tutorial é muito útil também ....
Ivans
Outro excelente recurso git .
Desconhecido
Seria stackoverflow.com/questions/2959443/... ajuda? (não para a git svnparte ' ', apenas para a git rebaseparte ' ')
VonC 16/06/10
@VonC, sim, é exatamente isso. Se você deseja copiar o pouco relevante da sua resposta aqui, vou assinalar-lo (eu realmente vai desta vez, eu prometo!)
Benjol
tudo bem ... eu vou morder;) extratos relevantes postados.
VonC 16/06/10

Respostas:

244

TL; DR;

Para resumir (como Benubird comenta ), quando:

git checkout A
git rebase   B    # rebase A on top of B
  • localé B(rebase para ),
  • remote é A

E:

git checkout A
git merge    B    # merge B into A
  • localé A(intercalação em ),
  • remote é B

Uma rebase muda ours(a ramificação atual antes do início da rebase) e theirs(a ramificação na qual você deseja rebase).


O kutschkem ressalta que, em um contexto de fusão de ferramentas da GUI :

  • referências locais confirmadas parcialmente reformuladas : " ours" (a ramificação upstream)
  • remoto refere-se às alterações recebidas : " theirs" - a ramificação atual antes da rebase.

Veja ilustrações na última parte desta resposta.


Inversão quando rebase

A confusão pode estar relacionada à inversão ourse theirsdurante uma rebase .
(extratos relevantes)

git rebasepágina de manual :

Observe que uma mesclagem de rebase funciona repetindo cada confirmação da ramificação de trabalho na parte superior da <upstream>ramificação.

Por esse motivo, quando ocorre um conflito de mesclagem:

  • o lado relatado como " ours" é a série rebaseada até agora, começando com <upstream>,
  • e ' theirs' é o ramo de trabalho. Em outras palavras, os lados são trocados.

Inversão ilustrada

Em uma mesclagem

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    \
     \
      \--y--y--y <- other branch to merge

, não alteramos o ramo atual 'B'; portanto, o que temos ainda é o que estávamos trabalhando (e nos fundimos de outro ramo)

x--x--x--x--x---------o(*)  MERGE, still on branch B
    \       ^        /
     \     ours     /
      \            /
       --y--y--y--/  
               ^
              their

Em uma rebase:

Mas, em uma rebase , trocamos de lado, porque a primeira coisa que uma rebase faz é fazer o checkout da ramificação upstream! (para reproduzir as confirmações atuais em cima dela)

x--x--x--x--x(*) <- current branch B
    \
     \
      \--y--y--y <- upstream branch

A git rebase upstreammudará primeiro HEADde B para o ramo upstream HEAD(daí a troca de 'nosso' e 'deles' em comparação com o ramo de trabalho "atual" anterior).)

x--x--x--x--x <- former "current" branch, new "theirs"
    \
     \
      \--y--y--y(*) <- upstream branch with B reset on it,  
                       new "ours", to replay x's on it

, e a rebase repetirá os "commits" deles na nova ramificação "our" B:

x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
    \
     \
      \--y--y--y--x'--x'--x'(*) <-  branch B with HEAD updated ("ours")
               ^
               |
        upstream branch

Nota: a noção "upstream" é o conjunto referencial de dados (um repositório all ou, como aqui, uma ramificação, que pode ser uma ramificação local ) a partir da qual os dados são lidos ou aos quais novos dados são adicionados / criados.


' local' e ' remote' vs. ' mine' e ' theirs'

Pandawood acrescenta nos comentários :

Para mim, a questão ainda permanece, que é "local" e quem é "remoto" (uma vez que os termos "nosso" e "deles" não são usados ​​para rebasear no git, referir-se a eles parece tornar a resposta mais confusa) .

GUI git mergetool

kutschkem acrescenta, e com razão:

Ao resolver conflitos, o git dirá algo como:

local: modified file and remote: modified file. 

Tenho certeza de que a pergunta visa a definição de local e remoto neste momento. Nesse ponto, parece-me, pela minha experiência, que:

  • referências locais confirmadas parcialmente reformuladas : " ours" (a ramificação upstream)
  • remoto refere-se às alterações recebidas : " theirs" - a ramificação atual antes da rebase.

git mergetoolde fato menciona 'local' e 'remote' :

Merging:
f.txt

Normal merge conflict for 'f.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

Por exemplo, o KDiff3 iria exibir a resolução merge como assim :

kdiff3

E fusão iria exibi-lo também :

Diferença de fusão

O mesmo para o VimDiff , que exibe :

Invoque o Vimdiff como uma ferramenta de fusão com o git mergetool -t gvimdiff. Versões recentes do Git invocam o Vimdiff com o seguinte layout de janela:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • LOCAL:
    Um arquivo temporário que contém o conteúdo do arquivo na ramificação atual.
  • BASE:
    Um arquivo temporário que contém a base comum para a mesclagem.
  • REMOTE:
    Um arquivo temporário que contém o conteúdo do arquivo a ser mesclado.
  • MERGED:
    O arquivo que contém os marcadores de conflito.

O Git executou o máximo possível de resolução automática de conflitos e o estado desse arquivo é uma combinação de ambos LOCALe de REMOTEmarcadores de conflito em torno de qualquer coisa que o Git não pudesse resolver por si próprio.
O mergetooldeve gravar o resultado da resolução neste arquivo.

VonC
fonte
13
Para mim, a questão ainda permanece, que é "local" e quem é "remoto" (uma vez que os termos "nosso" e "deles" não são usados ​​ao rebasear no git, referir-se a eles parece tornar a resposta mais confusa) . A pergunta é "quem é local e que é remota" - assim uma resposta certamente requer mencionar as palavras "local" e "remota"
PandaWood
@PandaWood: "local" é "ramo atual" (que se torna "deles"), "remoto" é "ramo upstream" (que se torna "nosso").
VonC 29/07
3
Assim, para resumir: quando você git checkout A; git rebase Blocal é B, remoto é A. Tudo o que eu precisava saber ...
Benubird
1
O git é um clusterfk de usabilidade. isso não faz sentido: quando você git checkout A; git rebase Blocal é B, remoto é um . Se eu checkout A, então eu estou navegando na os arquivos como eles existem em A, como é que de qualquer forma o controle remoto ? (Não estou dizendo que Benubird está errado; estou dizendo que o git tem um UX estúpido)
Rafa
1
@VonC sure; meu ponto (retórico) é que não é necessário ler a documentação, olhar os diagramas e ter que navegar pelo StackOverflow. Se ao menos o comando desse um feedback claro e inequívoco. Por exemplo, em vez de local / remoto / deles / nosso / meu / seu, apenas mostre {branch A}e {branch B}ou similar.
Rafa
45

A linha inferior

git rebase

  • LOCAL = a base estiver rebasing para
  • REMOTE = os commits que você está subindo no topo

mesclar git

  • LOCAL = o ramo original no qual você está mesclando
  • REMOTE = o outro ramo cujo commit você está mesclando

Em outras palavras, LOCAL é sempre o original e REMOTE é sempre o cara cujos commits não existiam antes, porque eles estão sendo mesclados ou reformulados no topo

Prove!

Certamente. Não aceite minha palavra! Aqui está um experimento fácil que você pode fazer para ver por si mesmo.

Primeiro, verifique se o git mergetool está configurado corretamente. (Se não o fizesse, provavelmente não estaria lendo esta pergunta de qualquer maneira.) Em seguida, encontre um diretório para trabalhar.

Configure seu repositório:

md LocalRemoteTest
cd LocalRemoteTest

Crie uma confirmação inicial (com um arquivo vazio):

git init
notepad file.txt  (use the text editor of your choice)
  (save the file as an empty file)
git add -A
git commit -m "Initial commit."

Crie uma confirmação em uma ramificação que não seja mestre:

git checkout -b notmaster
notepad file.txt
  (add the text: notmaster)
  (save and exit)
git commit -a -m "Add notmaster text."

Crie uma confirmação na ramificação principal:

git checkout master
notepad file.txt
  (add the text: master)
  (save and exit)
git commit -a -m "Add master text."

gitk --all

Nesse ponto, seu repositório deve ficar assim:

Repositório com uma confirmação de base e duas ramificações de uma confirmação

Agora, para o teste de rebase:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster

Agora, o teste de mesclagem. Feche sua ferramenta de fusão sem salvar as alterações e, em seguida, cancele a rebase:

git rebase --abort

Então:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)

Seus resultados devem ser os mesmos mostrados no topo.

Ryan Lundy
fonte
1
+1. Que esclarece as local/ remoteos aspectos eu lutava com a minha própria resposta acima (que é mais sobre a inversão do oursvs theirsde qualquer maneira)
VonC
3

Não entendi exatamente o seu problema, mas acho que o diagrama a seguir resolve seu problema. (Rebase: Repositório Remoto ---> Área de Trabalho)

http://assets.osteele.com/images/2008/git-transport.png

Fonte: Meu fluxo de trabalho Git

Chathuranga Chandrasekara
fonte