Qual è il significato preciso di "nostro" e "loro" in git?


323

Potrebbe sembrare una domanda troppo semplice, ma ho cercato risposte e ora sono più confuso di prima.

Cosa significano "nostro" e "loro" in git quando unisco il mio ramo all'altro ramo? Entrambi i rami sono "nostri".

In un conflitto di unione "nostro" è sempre visualizzata la parte superiore delle due versioni?

Il "nostro" si riferisce sempre al ramo che HEAD indicava quando è iniziata l'unione? Se è così, allora perché non usare un chiaro riferimento possessivo come "ramo corrente" invece di usare un pronome possessivo come "nostro" che è referenzialmente ambiguo (dal momento che entrambi i rami sono tecnicamente nostri)?

O semplicemente usa il nome del ramo (invece di dire "nostro", dì semplicemente "maestro locale" o simile)?

La parte più confusa per me è se specifico nel file .gitattributes di un ramo specifico. Diciamo che nel ramo di test ho il seguente file .gitattributes:

config.xml merge=ours

Ora controllo e punto HEAD per padroneggiare, quindi unisco in prova . Poiché il master è nostro e il test di .gitattributes non è stato verificato, avrà anche un effetto? Se ha un effetto, dal momento che il maestro è ora "nostro", allora cosa accadrà?

Risposte:


375

Sospetto che tu sia confuso qui perché è fondamentalmente confuso. A peggiorare le cose, l'intera roba nostra / loro cambia ruolo (diventa all'indietro) quando stai facendo un rebase.

In definitiva, nel corso di una git merge, il ramo "nostro" si riferisce al ramo si sta fondendo in :

git checkout merge-into-ours

e il ramo "loro" si riferisce al ramo (singolo) che stai unendo:

git merge from-theirs

e qui "nostra" e "loro" fa un certo senso, come anche se "loro" è probabilmente la vostra in ogni caso, "loro" non è quello che eri su quando è stato eseguito git merge.

Mentre l'utilizzo del nome del ramo effettivo potrebbe essere piuttosto interessante, cade a pezzi in casi più complessi. Ad esempio, invece di quanto sopra, potresti fare:

git checkout ours
git merge 1234567

dove stai unendo per commit-ID non elaborato. Peggio ancora, puoi persino farlo:

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

nel qual caso non ci sono non nomi filiali coinvolte!

Penso che sia di scarso aiuto qui, ma in effetti, nella gitrevisionssintassi , puoi fare riferimento a un singolo percorso nell'indice in base al numero, durante un'unione in conflitto

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

Lo stage n. 1 è l'antenato comune dei file, lo stage n. 2 è la versione del ramo di destinazione e lo stage n. 3 è la versione da cui si stanno fondendo.


Il motivo per cui le nozioni "nostre" e "loro" vengono scambiate durante rebasequesta fase è che rebase funziona eseguendo una serie di selezioni di ciliegie, in un ramo anonimo (modalità HEAD staccata). Il ramo target è il ramo anonimo e il ramo Merge-from è il ramo originale (pre-rebase): quindi "--ours" significa che un rebase anonimo sta costruendo mentre "--theirs" significa "il nostro ramo in fase di rebasing" .


Per quanto riguarda la voce gitattributes: potrebbe avere un effetto: "nostro" significa davvero "usa la fase 2" internamente. Ma come notate, al momento non è in atto, quindi non dovrebbe avere un effetto qui ... beh, a meno che non lo copiate nell'albero di lavoro prima di iniziare.

Inoltre, questo vale per tutti i nostri e nostri usi, ma alcuni sono a livello di file intero ( -s oursper una strategia di unione; git checkout --oursdurante un conflitto di unione) e alcuni sono su base pezzo per pezzo ( -X ourso -X theirsdurante un-s recursive merge). Il che probabilmente non aiuta con nessuna confusione.

Non ho mai trovato un nome migliore per questi, però. E: vedi la risposta di VonC a un'altra domanda, dove git mergetoolintroduce ancora più nomi per questi, chiamandoli "locali" e "remoti"!


28
+1. Circa la nostra e la loro essere invertite durante rebase, vedi anche: stackoverflow.com/a/2960751/6309 e stackoverflow.com/a/3052118/6309
VonC

1
Due cose "si fondono" tra loro. Quando si verifica un'unione, entrambe le parti si uniscono "l'una nell'altra". Ritengo che sarebbe errato affermare che una delle due parti "non si fonde in nulla". Se non ci sono nomi di filiali coinvolti (come fai notare), allora ci sono nomi di commit coinvolti (potresti dire "7777777" e "1234567" invece di "nostri" e "loro"). Capisco cosa succede durante un rebase e non lo trovo affatto confuso. Penso che "HEAD" e "incoming" funzionerebbero meglio di "nostri" e "loro" perché c'è sempre un "HEAD" (che sia distaccato o meno).
CommaToast,

15
Immagino che dal momento che la testa è la sede della mente, che è la fonte dell'identità, che è la fonte del sé, ha un po 'più senso pensare a qualunque cosa HEAD stia indicando come "mia" ("nostra", poiché Immagino me e HEAD ne fa due). Se non altro, sarà solo un buon dispositivo mnemonico.
CommaToast,

1
Detto questo, mi piace ancora fare una copia fisica dell'intero repository prima di fare qualcosa di simile al rebasing ...: D
Comma Toast

3
"nel qual caso non ci sono nomi di rami coinvolti!" ... Quindi dovrebbe usare invece il commento / hash di commit. Qualunque cosa riesca a mettere le mani. Praticamente qualsiasi cosa sarebbe meglio della "nostra" e della "loro". Mi chiedo quante migliaia di ore di sviluppo questa confusione sia evaporata. la risposta di git alla "parse più irritante" del C ++;)
Jarrod Smith

49

Il ' nostro ' in Git si riferisce al ramo di lavoro originale che ha parte autorevole / canonica della storia di Git.

Il ' loro ' si riferisce alla versione che contiene il lavoro per essere riformulato (le modifiche devono essere riprodotte sul ramo corrente).

Questo può sembrare essere scambiato a persone che non sono consapevoli del fatto che fare il rebasing (ad es. git rebase) Sta effettivamente mettendo in attesa il tuo lavoro (che è il loro ) al fine di rigiocare la storia canonica / principale che è nostra , perché stiamo rinnovando il nostro cambia come lavoro di terze parti.

La documentazione per è git-checkoutstata ulteriormente chiarita in Git> = 2.5.1 come da f303016commit :

--ours --theirs

Quando si verificano i percorsi dall'indice, controllare la fase # 2 ("nostra") o # 3 ("loro") per i percorsi non uniti.

Si noti che durante git rebasee git pull --rebase, 'nostro' e 'loro' possono apparire scambiati; --oursfornisce la versione dal ramo su cui vengono modificate le modifiche, mentre --theirsfornisce la versione dal ramo che contiene il lavoro che viene modificato.

Questo perché rebaseviene utilizzato in un flusso di lavoro che tratta la cronologia del telecomando come quella canonica condivisa e considera il lavoro svolto sul ramo che si sta riassumendo come lavoro di terze parti da integrare e si assume temporaneamente il ruolo di il custode della storia canonica durante il rebase. Come custode della storia canonica, devi vedere la storia dal remoto come ours(cioè "la nostra storia canonica condivisa"), mentre quello che hai fatto sul tuo ramo laterale come theirs(cioè "il lavoro di un collaboratore su di esso").

Perché git-mergeè spiegato nel modo seguente:

nostro

Questa opzione obbliga gli hunk in conflitto a risolversi automaticamente in modo chiaro favorendo la nostra versione. Le modifiche rispetto all'altro albero che non sono in conflitto con la nostra parte si riflettono sul risultato della fusione. Per un file binario, l'intero contenuto è preso dalla nostra parte.

Questo non dovrebbe essere confuso con la nostra strategia di unione, che non guarda nemmeno a ciò che contiene l'altro albero. Scarta tutto ciò che l'altro albero ha fatto, dichiarando che la nostra storia contiene tutto ciò che è accaduto in esso.

il loro

Questo è il nostro contrario.

Inoltre, ecco spiegato come usarli:

Il meccanismo ( git mergee i git pullcomandi) di unione consente di scegliere le strategie di unione back-end con l' -sopzione. Alcune strategie possono anche prendere le proprie opzioni, che possono essere passate dando -X<option>argomenti a git mergee / o git pull.


Quindi a volte può essere fonte di confusione, ad esempio:

  • git pull origin masterdov'è il -Xoursnostro locale, -Xtheirsè il loro ramo (remoto)
  • git pull origin master -rdov'è il -Xoursloro (remoto), -Xtheirsè nostro

Quindi il secondo esempio è opposto al primo, perché stiamo riordinando il nostro ramo sopra quello remoto, quindi il nostro punto di partenza è remoto e le nostre modifiche sono trattate come esterne.

Simile per git mergestrategie ( -X ourse -X theirs).


2
questa risposta sembra obsoleta => "git merge --ours" non è un'opzione valida
Alexander Mills

@AlexanderMills La risposta non ha parlato git merge, ma git pulle git checkoutcome esempio. Se ti piace usare questo parametro con git merge, dovresti usare -X ours. Puoi ancora usare la --ourssintassi per git checkout. Ho chiarito ulteriormente la risposta.
Kenorb,

46

So che è stata data una risposta, ma questo problema mi ha confuso così tante volte che ho creato un piccolo sito Web di riferimento per aiutarmi a ricordare: https://nitaym.github.io/ourstheirs/

Ecco le basi:

Unisce:

$ git checkout master 
$ git merge feature

Se vuoi selezionare la versione in master:

$ git checkout --ours codefile.js

Se vuoi selezionare la versione in feature:

$ git checkout --theirs codefile.js

rebases:

$ git checkout feature 
$ git rebase master 

Se vuoi selezionare la versione in master:

$ git checkout --ours codefile.js

Se vuoi selezionare la versione in feature:

$ git checkout --theirs codefile.js

(Questo è per i file completi, ovviamente)


1
Quel sito web è super utile. Lo stile del diagramma di flusso e le parole con codice colore rendono il sito molto più facile da capire rispetto alle risposte SO. Grazie.
Ron

10
  • Il nostro : questo è il ramo in cui ti trovi attualmente.
  • Loro : questo è l'altro ramo usato nella tua azione.

Quindi, se siete sul ramo di rilascio / 2.5 e si uniscono ramo caratteristica dei nuovi pulsanti / in esso, allora il contenuto come si trova nel rilascio / 2.5 è cosa nostra si riferisce e il contenuto come si trova su nuovi pulsanti-funzione / è quello che loro si riferisce per. Durante un'azione di unione questo è piuttosto semplice.

L'unico problema per la maggior parte delle persone è il caso rebase . Se si esegue una nuova base anziché una normale unione, i ruoli vengono scambiati. Com'è quello? Bene, questo è causato esclusivamente dal modo in cui funziona la rebasing. Pensa a rebase di funzionare in questo modo:

  1. Tutti i commit che hai fatto dall'ultimo pull sono stati spostati su un ramo a parte, chiamiamolo BranchX .
  2. Dai un'occhiata al capo del tuo ramo attuale, scartando tutte le modifiche locali che hai avuto ma in questo modo recuperando tutte le modifiche che altri hanno fatto per quel ramo.
  3. Ora ogni commit su BranchX è selezionato in modo accurato dal vecchio al nuovo al tuo attuale ramo.
  4. BranchX viene nuovamente eliminato e quindi non verrà mai visualizzato in nessuna cronologia.

Certo, non è proprio quello che sta succedendo, ma è un bel modello mentale per me. E se guardi 2 e 3, capirai perché i ruoli vengono scambiati ora. A partire da 2, il tuo ramo attuale è ora il ramo dal server senza nessuna delle tue modifiche, quindi questo è nostro (il ramo in cui ti trovi). Le modifiche apportate ora si trovano su un ramo diverso che non è quello attuale ( BranchX ) e pertanto tali cambiamenti (nonostante siano stati apportati cambiamenti) sono loro (l'altro ramo utilizzato nella tua azione).

Ciò significa che se ti unisci e vuoi che le tue modifiche vincano sempre, diresti a git di scegliere sempre "le nostre", ma se ti ribassi e vuoi che tutte le tue modifiche vincano sempre, dici a git di scegliere sempre "loro".


3

So che non spiega il significato, ma mi sono fatto una piccola immagine, come riferimento per ricordare quale usare:

inserisci qui la descrizione dell'immagine

Spero che sia d'aiuto!

PS: controlla anche il link nella risposta di Nitay 🙂


3

Pubblicherò il mio memo qui, perché devo tornare qui ancora e ancora.

SCENARIO 1. Sviluppatore normale: sei uno sviluppatore che non riesce a unirsi mastere deve giocare featuresolo con i rami.

Caso 1: il maestro è un re. Vuoi aggiornare il tuo featureramo (= rebase in master), perché mastercontiene nuovi aggiornamenti di dipendenze e vuoi sovrascrivere le tue modeste modifiche.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Caso 2: sei un re. Vuoi ridisporre il tuo featureramo alle mastermodifiche. Ma hai fatto più di quanto non avessero i tuoi colleghi e desideri utilizzare le tue modifiche in via prioritaria.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

IMPORTANTE: come puoi vedere, gli sviluppatori dovrebbero preferire rebasee ripeterlo ogni mattina come esercizi / caffè.

SCENARIO 2. Merging-sensei: sei un team leader e vuoi unire altri rami e spingere un risultato unito direttamente a un master. masterè un ramo che cambierai.

Caso 1: il padrone è un re Vuoi unire il ramo di terze parti, ma masterè una priorità. featureè un ramo che ha fatto il tuo anziano.

git checkout feature
git pull

git checkout master
git merge -X ours master

Caso 2: le nuove modifiche sono un re Quando il tuo sviluppatore senior ha rilasciato un cool featuree vuoi sovrascrivere la vecchia s ** t nel masterramo.

git checkout feature
git pull

git checkout master
git merge -X theirs master

RICORDA: Ricordare a mezzanotte quale scegliere: masterè oursSEMPRE. Ed theirsè una cosa featureche hanno fatto loro.


2

Da git checkoututilizzo 's:

-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

Quando si risolvono i conflitti di unione, è possibile eseguire git checkout --theirs some_filee git checkout --ours some_fileripristinare rispettivamente il file sulla versione corrente e sulle versioni in arrivo.

Se hai terminato git checkout --ours some_fileo git checkout --theirs some_filedesideri ripristinare il file alla versione di unione a 3 vie del file, puoi farlo git checkout --merge some_file.

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.