Qual é o significado preciso de "nosso" e "deles" no git?

323

Pode parecer uma pergunta muito básica, mas procurei respostas e estou mais confusa agora do que antes.

O que "nossos" e "deles" significam no git ao mesclar minha ramificação em minha outra ramificação? Ambos os ramos são "nossos".

Em um conflito de mesclagem, o "nosso" é sempre a parte superior das duas versões exibidas?

"Our" sempre se refere ao ramo que o HEAD estava apontando quando a mesclagem começou? Se sim, por que não usar uma referência possessiva clara como "ramo atual" em vez de usar um pronome possessivo como "nosso" que seja referencialmente ambíguo (já que ambos os ramos são tecnicamente nossos)?

Ou apenas use o nome do ramo (em vez de dizer "nosso", apenas diga "mestre local" ou algo semelhante)?

A parte mais confusa para mim é se eu especificar no arquivo .gitattributes de uma ramificação específica. Vamos dizer que no ramo de teste eu tenho o seguinte arquivo .gitattributes:

config.xml merge=ours

Agora faço o checkout e aponto HEAD para dominar e, em seguida, entrei no teste . Como o mestre é nosso e o atributo .gitattributes do teste não está marcado, isso terá algum efeito? Se isso tem efeito, já que o mestre agora é "nosso", o que acontecerá?

CommaToast
fonte

Respostas:

375

Eu suspeito que você está confuso aqui porque é fundamentalmente confuso. Para piorar as coisas, todo o nosso / o deles troca de papéis (fica para trás) quando você está fazendo uma nova revisão.

Em última análise, durante uma git merge, o ramo "nosso" refere-se ao ramo que você está fundindo em :

git checkout merge-into-ours

e o ramo "deles" refere-se ao ramo (único) que você está mesclando:

git merge from-theirs

e aqui "nosso" e "deles" faz algum sentido, pois, embora "deles" é provavelmente seu de qualquer maneira, "deles" não é o que você estava em quando você executou git merge.

Embora o uso do nome real da ramificação possa ser bem legal, ele se desfaz em casos mais complexos. Por exemplo, em vez do acima, você pode fazer:

git checkout ours
git merge 1234567

onde você está mesclando por commit-ID bruto. Pior, você pode até fazer isso:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

nesse caso, não nomes de filiais envolvidos!

Eu acho que é de pouca ajuda aqui, mas, de fato, na gitrevisionssintaxe , você pode se referir a um caminho individual no índice por número, durante uma mesclagem conflitante

git show :1:README
git show :2:README
git show :3:README

O estágio 1 é o ancestral comum dos arquivos, o estágio 2 é a versão do ramo de destino e o estágio 3 é a versão da qual você está mesclando.


A razão pela qual as noções "nossa" e "deles" são trocadas durante o processo rebaseé que a rebase funciona fazendo uma série de escolhas de cereja, em uma ramificação anônima (modo HEAD desanexado). A ramificação de destino é a ramificação anônima e a ramificação de mesclagem é sua ramificação original (pré-rebase): então "--ours" significa que a rebase anônima está sendo construída enquanto "--theirs" significa "nossa ramificação sendo rebased" .


Quanto à entrada gitattributes: poderia ter um efeito: "nosso" realmente significa "usar o estágio # 2" internamente. Mas, como você observa, ele não está realmente no lugar no momento, portanto não deve ter efeito aqui ... bem, a menos que você o copie na árvore de trabalho antes de começar.

Além disso, a propósito, isso se aplica a todos os usos nossos e deles, mas alguns estão em um nível de arquivo inteiro ( -s ourspara uma estratégia de mesclagem; git checkout --oursdurante um conflito de mesclagem) e alguns são peça por peça ( -X oursou -X theirsdurante uma -s recursivemesclar). O que provavelmente não ajuda com nenhuma confusão.

Eu nunca inventei um nome melhor para eles, no entanto. E: veja a resposta do VonC para outra pergunta, onde git mergetoolintroduz ainda mais nomes para eles, chamando-os de "local" e "remoto"!

torek
fonte
28
+1. Sobre os nossos e os deles serem revertidos durante o rebase, consulte também: stackoverflow.com/a/2960751/6309 e stackoverflow.com/a/3052118/6309
VonC
1
Duas coisas "se fundem". Quando ocorre uma mesclagem, os dois lados se fundem "um no outro". Eu acho que seria incorreto dizer que um dos dois lados "não está se fundindo em nada". Se não houver nomes de ramificações envolvidos (como você indica), haverá nomes de confirmação envolvidos (você pode dizer "7777777" e "1234567" em vez de "nosso" e "deles"). Entendo o que acontece durante um rebase e não acho nada confuso. Eu acho que "HEAD's" e "de entrada" funcionariam melhor que "nossos" e "deles" porque sempre existe um "HEAD" (independente ou não).
CommaToast
15
Eu acho que desde que a cabeça é o assento da mente, que é a fonte da identidade, que é a fonte do eu, faz um pouco mais de sentido pensar no que quer que o HEAD esteja apontando como sendo "meu" ("nosso", pois Eu acho que eu e a cabeça faz dois). Se nada mais, isso será apenas um bom dispositivo mnemônico.
CommaToast
1
Dito isto, eu ainda gosto de fazer uma cópia física de todo o repo antes de fazer algo como rebasing ...: D
CommaToast
3
"nesse caso, não há nomes de ramificações envolvidos!" ... Portanto, ele deve usar o comentário / hash de confirmação. O que quer que ele possa colocar em suas mãos. Praticamente qualquer coisa seria melhor que "nosso" e "deles". Eu me pergunto quantas milhares de horas de desenvolvimento essa confusão evaporou. resposta do git à "análise mais vexatória" do C ++;)
Jarrod Smith
49

O ' nosso ' no Git está se referindo ao ramo de trabalho original que possui parte autoritária / canônica da história do git.

O ' deles ' refere-se à versão que contém o trabalho para ser refazida (alterações a serem repetidas na ramificação atual).

Isso pode parecer ter sido trocado por pessoas que não sabem que fazer o rebaseamento (por exemplo git rebase) está realmente retendo seu trabalho (que é deles ) para reproduzir a história canônica / principal que é nossa , porque estamos refazendo nossa muda conforme o trabalho de terceiros.

A documentação para git-checkoutfoi esclarecida em Git> = 2.5.1 conforme f303016commit :

--ours --theirs

Ao verificar caminhos a partir do índice, verifique o estágio # 2 ('nosso') ou # 3 ('deles') quanto a caminhos não imersos.

Observe que durante git rebasee git pull --rebase, 'nosso' e 'deles' podem aparecer trocados; --oursfornece a versão da ramificação na qual as alterações são reformuladas, enquanto --theirsfornece a versão da ramificação que mantém o trabalho que está sendo reformulado.

Isso ocorre porque rebaseé usado em um fluxo de trabalho que trata o histórico no controle remoto como o canônico compartilhado e trata o trabalho realizado na ramificação que você está refazendo como o trabalho de terceiros a ser integrado, e você está assumindo temporariamente o papel de o detentor da história canônica durante o rebase. Como guardião da história canônica, você precisa visualizá-la do controle remoto como ours(por exemplo, "nossa história canônica compartilhada"), enquanto o que você fez do seu lado se ramifica como theirs(por exemplo, "o trabalho de um colaborador em cima").

Pois git-mergeé explicado da seguinte maneira:

nosso

Esta opção força os pedaços conflitantes a serem resolvidos automaticamente de maneira limpa, favorecendo nossa versão. As alterações da outra árvore que não conflitam com o nosso lado são refletidas no resultado da mesclagem. Para um arquivo binário, todo o conteúdo é retirado do nosso lado.

Isso não deve ser confundido com a nossa estratégia de mesclagem, que nem sequer olha para o que a outra árvore contém. Ele descarta tudo o que a outra árvore fez, declarando que a nossa história contém tudo o que aconteceu nela.

deles

Este é o oposto do nosso.

Além disso, aqui é explicado como usá-los:

O mecanismo de mesclagem ( git mergee git pullcomandos) permite que as estratégias de mesclagem de back-end sejam escolhidas com a -sopção Algumas estratégias também podem ter suas próprias opções, que podem ser passadas fornecendo -X<option>argumentos para git mergee / ou git pull.


Às vezes, pode ser confuso, por exemplo:

  • git pull origin masteronde -Xoursé o nosso local, -Xtheirsé o ramo deles (remoto)
  • git pull origin master -ronde -Xoursé deles (remoto), -Xtheirsé nosso

Portanto, o segundo exemplo é oposto ao primeiro, porque estamos refazendo nossa ramificação em cima da remota, portanto nosso ponto de partida é remoto e nossas alterações são tratadas como externas.

Semelhante para git mergeestratégias ( -X ourse -X theirs).

kenorb
fonte
2
esta resposta parece fora de data => "--ours mesclagem git" não é uma opção válida
Alexander Mills
@AlexanderMills A resposta não falou sobre git merge, mas git pulle git checkoutcomo exemplo. Se você gosta de usar esse parâmetro git merge, deve usar -X ours. Você ainda pode usar a --ourssintaxe para git checkout. Esclarei a resposta ainda mais.
Kenorb # 23/16
46

Sei que isso foi respondido, mas esse problema me confundiu muitas vezes. Criei um pequeno site de referência para me lembrar: https://nitaym.github.io/ourstheirs/

Aqui estão os princípios básicos:

Mescla:

$ git checkout master 
$ git merge feature

Se você deseja selecionar a versão em master:

$ git checkout --ours codefile.js

Se você deseja selecionar a versão em feature:

$ git checkout --theirs codefile.js

Rebase:

$ git checkout feature 
$ git rebase master 

Se você deseja selecionar a versão em master:

$ git checkout --ours codefile.js

Se você deseja selecionar a versão em feature:

$ git checkout --theirs codefile.js

(Isso é para arquivos completos, é claro)

Nitay
fonte
1
Esse site é super útil. O estilo do fluxograma e as palavras codificadas por cores tornam o site muito mais fácil de entender do que as respostas do SO. Obrigado.
Ron
10
  • Nosso : Este é o ramo em que você está atualmente.
  • Deles : Este é o outro ramo usado em sua ação.

Portanto, se você está no release / 2.5 da filial e mescla o recurso de ramificação / novos botões nele, o conteúdo conforme encontrado na liberação / 2.5 é o que o nosso se refere e o conteúdo conforme encontrado no recurso / novos botões é o que eles se referem para. Durante uma ação de mesclagem, isso é bastante simples.

O único problema para o qual muitas pessoas se enquadram é o caso de rebase . Se você fizer uma nova base em vez de uma mesclagem normal, as funções serão trocadas. Como é isso? Bem, isso é causado apenas pela maneira como o rebaseamento funciona. Pense em rebase para funcionar assim:

  1. Todas as confirmações efetuadas desde o último pull são movidas para uma ramificação própria, vamos chamá- lo de BranchX .
  2. Você faz checkout do cabeçalho de sua ramificação atual, descartando as alterações locais que você teve, mas recuperando todas as alterações que outras pessoas fizeram nessa ramificação.
  3. Agora, todas as confirmações no BranchX são selecionadas de maneira antiga para novas em sua filial atual.
  4. O BranchX é excluído novamente e, portanto, nunca será exibido em nenhum histórico.

Claro, isso não é realmente o que está acontecendo, mas é um modelo de mente legal para mim. E se você olhar para 2 e 3, entenderá por que as funções são trocadas agora. A partir de 2, sua ramificação atual agora é a ramificação do servidor sem nenhuma alteração; portanto, essa é nossa (a ramificação em que você está). As alterações feitas agora estão em um ramo diferente que não é o atual ( BranchX ) e, portanto, essas alterações (apesar de terem sido as alterações que você fez) são delas (o outro ramo usado em sua ação).

Isso significa que, se você mesclar e quiser que suas alterações sempre vencam, você diria ao git para sempre escolher "nosso", mas se você se recuperar e quiser que todas as suas alterações sempre vencam, você diz ao git para sempre escolher "deles".

Mecki
fonte
3

Eu sei que isso não explica o significado, mas criei uma pequena imagem, como referência para lembrar qual usar:

insira a descrição da imagem aqui

Espero que ajude!

PS - Verifique também o link na resposta do Nitay 🙂

Kamafeather
fonte
3

Vou postar meu memorando aqui, porque tenho que voltar aqui novamente.

CENÁRIO 1. Desenvolvedor normal: você é um desenvolvedor que não pode se unir mastere precisa jogar featureapenas com ramificações.

Caso 1: o mestre é um rei. Você deseja atualizar sua featureramificação (= rebase para master), porque mastercontém novas atualizações de dependências e deseja substituir suas alterações modestas.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Caso 2: você é um rei. Você deseja refazer sua featureramificação para masteralterações. Mas você fez mais do que seus colegas fizeram e deseja usar suas próprias alterações em uma prioridade.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

IMPORTANTE: Como você pode ver, desenvolvedores normais devem preferir rebasee repeti-lo todas as manhãs como exercícios / café.

CENÁRIO 2. Sensibilidade de mesclagem: você é líder de equipe e deseja mesclar outras ramificações e enviar um resultado mesclado diretamente para um mestre. masteré um ramo que você vai mudar.

Caso 1: mestre é rei Você deseja mesclar ramificações de terceiros, mas masteré uma prioridade. featureé um ramo que seu sénior fez.

git checkout feature
git pull

git checkout master
git merge -X ours master

Caso 2: novas mudanças são o rei Quando seu desenvolvedor sênior lançou um cool featuree você deseja sobrescrever o antigo erro no masterramo.

git checkout feature
git pull

git checkout master
git merge -X theirs master

LEMBRE-SE: Lembrar à meia-noite qual escolher: masteré oursSEMPRE. E theirsé featureisso que eles fizeram.

DenisKolodin
fonte
2

Do git checkoutuso:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

Ao resolver conflitos de mesclagem, você pode fazer git checkout --theirs some_filee git checkout --ours some_fileredefinir o arquivo para a versão atual e as versões recebidas, respectivamente.

Se você fez git checkout --ours some_fileou git checkout --theirs some_filegostaria de redefinir o arquivo para a versão de mesclagem em três vias, pode fazê-lo git checkout --merge some_file.

Joshua Ryan
fonte