Significato di Git checkout doppio trattino


274

Qual è il significato dei doppi trattini prima del nome del file in questo comando git?

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

Sono obbligatori? È equivalente a

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt

24
È un'espressione shell. Vedi unix.stackexchange.com/questions/11376/…
iltempo

15
@iltempo: è leggermente diverso per Git. Per Git, separa l'albero dai percorsi, nei casi in cui alberi e percorsi potrebbero apparire uguali.
Dietrich Epp,

@Dietrich_Epp. Vedo. Grazie per il chiarimento.
iltempo

Documentati anche in stackoverflow.com/a/1192194/6309
VonC

3
È un duplicato, ma questo duplicato è almeno googleable dalla query 'git double dash'.
thorn̈

Risposte:


376

Supponiamo di avere un file chiamato path/to/file.txtnel mio repository Git e di voler ripristinare le modifiche.

git checkout path/to/file.txt

Supponiamo ora che il file sia chiamato master...

git checkout master

Ops! Ciò ha invece cambiato i rami. Le --separa l'albero si desidera controllare fuori dalle file che si desidera controllare.

git checkout -- master

Ci aiuta anche se qualche mostro ha aggiunto un file chiamato -fal nostro repository:

git checkout -f      # wrong
git checkout -- -f   # right

Questo è documentato in git-checkout: Argomento Disambiguation .


12
Questo è vero per molti comandi bash, non solo per i comandi git, sì?
NHDaly

40
@NHDaly: Sì, è vero. Tuttavia, una nota terminologica: "Bash" ha solo pochi comandi (forse circa 20), la maggior parte dei comandi sono programmi separati da Bash. In realtà fa parte dello standard POSIX che --può essere utilizzato per separare le opzioni da altri argomenti, quindi lo vedrai su comandi come cpe mv(che non fanno parte di Bash).
Dietrich Epp,

6
Qualche idea sul perché questa sintassi non sia correttamente descritta nella checkoutdocumentazione dei comandi?
TanguyP

4
@DietrichEpp In diversi punti, è elencato come un possibile parametro per il checkoutcomando, ma da nessuna parte la documentazione spiega cosa fa o perché viene usato ... che alla fine mi ha portato qui.
chris,

7
@DietrichEpp Corretto, ma dopo aver letto la sintassi (e gli esempi) prima di arrivare a Stack Overflow, non capivo ancora perché uno avrebbe o non avrebbe voluto usarlo --. Come qualcuno che non proviene da un background Linux, non è ovvio cosa faccia. Per me, sembrava essere una sintassi specifica di git, senza una descrizione del suo scopo funzionale. Penso che sarebbe meglio avere una breve descrizione come le altre opzioni, o almeno un collegamento a una pagina man di linux .
chris,

109

Il doppio trattino "-" significa "fine dei flag della riga di comando", ovvero indica al comando precedente di non provare ad analizzare ciò che viene dopo le opzioni della riga di comando.


2
Per chiarezza, in gitquesto significa più di questo, poiché significa anche che l'argomento dopo il --non può essere un nome di ramo e, implicitamente, l'argomento precedente --non può essere un percorso di file.
Gem Taylor,

0

Si noti che non sarebbe necessario, poiché Git 2.5 (Q2 2015) a ' --' se l'argomento include il carattere jolly (* )

Un'euristica per aiutare la " git <cmd> <revs> <pathspec>" convenzione della riga di comando a catturare percorsi errati è assicurarsi che tutti i parametri non rev nella parte successiva della riga di comando siano nomi dei file nell'albero di lavoro, ma ciò significa che " git grep $str -- \*.c" deve essere sempre disambiguato con " --", perché nessuno sano di mente creerà un file il cui nome è letteralmente asterisco-punto-vedi.

Git 2.5 perde l'euristica nel dichiarare che con una stringa jolly l'utente probabilmente intendeva darci un pathspec .

git checkout 'a*'
# same as
git checkout -- 'a*'

Vedi commit 28fcc0b (02 maggio 2015) di Duy Nguyen ( nguyenlocduy) .
(Unito da Junio ​​C Hamano - gitster- in commit 949d167 , 19 maggio 2015)

pathspec: evitare la necessità di "-- " quando si utilizza il carattere jolly

Quando "-- " manca dalla riga di comando e un comando può prendere sia i giri che i percorsi, l'idea è se un argomento può essere visto sia come SHA-1 esteso sia come percorso, allora " --" è richiesto o git rifiuta di continuare.
Attualmente è implementato come:

  • (1) se un argomento è rev, allora non deve esistere in worktree
  • (2) altrimenti, deve esistere in worktree
  • (3) altro "--" è obbligatorio.

Queste regole funzionano per percorsi letterali, ma quando è coinvolto pathspec non letterale, richiede quasi sempre all'utente di aggiungere " --" perché non riesce (2) e (1) è raramente soddisfatto (prendere "*.c " per esempio, (1) viene soddisfatto se esiste un riferimento denominato " *.c").

Questa patch modifica un po 'le regole considerando qualsiasi *pathspec jolly valido ( ) esistente in worktree.
Le regole diventano:

  • (1) se un arg è un giro, allora deve esistere in worktree o non essere un pathspec jolly valido.
  • (2) altrimenti, esiste in worktree o è un pathspec jolly
  • (3) altrimenti, " --" è obbligatorio.

Con le nuove regole, " --" non è necessario la maggior parte delle volte quando è coinvolto il carattere jolly pathspec.


Con Git 2.26 (Q1 2020), la logica di chiarimento delle ambiguità per distinguere le revisioni e il pathspec è stata modificata in modo tale che i caratteri speciali glob con escape backslash non contino nella regola "caratteri jolly sono pathspec".

Vedi commit 39e21c6 (25 gennaio 2020) di Jeff King ( peff) .
(Unita da Junio ​​C Hamano - gitster- in commit 341f8a6 , 12 feb 2020)

verify_filename(): gestire le barre rovesciate nella regola "i caratteri jolly sono pathspecs"

Segnalato da: David Burström
Firmato da: Jeff King

Commit 28fcc0b71a ( pathspec: evita la necessità di " --" quando si utilizza il carattere jolly, 2015-05-02) consentito:

git rev-parse '*.c'

senza il doppio trattino.

Ma la regola che utilizza per verificare la presenza di caratteri jolly cerca effettivamente qualsiasi speciale glob.
Questo è eccessivamente liberale, in quanto significa che un modello che in realtà non esegue alcuna corrispondenza con caratteri jolly, come "a\b ", sarà considerato un pathspec.

Se hai un file del genere su disco, è presumibilmente quello che volevi.
Ma se non lo fai, i risultati sono confusi: piuttosto che dire " there's no such path a\b", lo accetteremo tranquillamente come pathspec che molto probabilmente non corrisponde a nulla (o almeno non a quello che intendevi).
Allo stesso modo, cercare il percorso " a\*b" non espande affatto la ricerca; troverà una sola voce " a*b".

Questo commit commuta la regola in modo che si attivi solo quando i metacaratteri glob espandono la ricerca, il che significa che entrambi i casi ora segnalano un errore (puoi comunque chiarire con " --", ovviamente; stiamo solo stringendo l'euristica DWIM).

( DWIM: fai quello che intendo )

Nota che non abbiamo testato affatto la funzione originale in 28fcc0b71a .
Quindi questa patch non solo verifica questi casi angolari, ma aggiunge anche un test di regressione per il comportamento esistente.

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.