Perché non c’è un’opzione specifica per il clone Git?

Alla luce di una recente domanda su SO , mi chiedo perché non c’è un’opzione in git clone tale che il puntatore HEAD del ramo appena creato punterà ad un commit specificato? Nella domanda precedente, OP sta cercando di fornire istruzioni sul commit specifico che i suoi utenti dovrebbero clonare.

Si noti che questa domanda non riguarda Come eseguire la clonazione su una particolare versione utilizzando il reset ; ma sul perché non c’è ?

Due risposte finora (al momento in cui ho scritto questo, ora ce ne sono altre) sono corrette in ciò che dicono, ma in realtà non rispondono alla domanda “perché”. Certo, la domanda “perché” è davvero difficile da rispondere, tranne che dagli autori dei vari bit di Git (e anche allora, e se due frequenti contributori Git davano due risposte diverse?).

Tuttavia, considerando la “filosofia” di Git per così dire, in generale, i vari protocolli di trasferimento funzionano nominando un riferimento . Se forniscono un SHA-1, è lo SHA-1 di quel riferimento . Per qualcuno che non ha già accesso diretto (ad esempio, riga di comando) al repository, nessuno dei comandi incorporati consente di fare riferimento a commit per ID. La cosa più vicina che riesco a trovare per una ragione – ed è in realtà una buona ragione 2 – è proprio questo nella documentazione di git upload-archive :

SICUREZZA

Per proteggere la privacy degli oggetti che sono stati rimossi dalla cronologia ma che potrebbero non essere stati ancora eliminati, git-upload-archive evita di servire archivi per commit e alberi che non sono raggiungibili dai riferimenti del repository. Tuttavia, poiché il calcolo della raggiungibilità degli oggetti è dispendioso dal punto di vista del calcolo, git-upload-archive implementa una serie di regole più rigide ma più facili da controllare …

Tuttavia, continua a dire:

Se l’opzione di configurazione uploadArchive.allowUnreachable è true, queste regole vengono ignorate ei client possono utilizzare espressioni sha1 arbitrarie. Questo è utile se non ti interessa la privacy degli oggetti irraggiungibili, o se il tuo database degli oggetti è già pubblicamente disponibile per l’accesso tramite non-smart-http.

che è particolarmente interessante dato che git clone ottiene tutti gli oggetti raggiungibili in primo luogo, dopo di che il clone locale potrebbe banalmente estrarre un commit dall’ID SHA-1 (e creare un nome di ramo locale che punta a quell’ID se lo si desidera, o lasciare semplicemente il tuo clonare in modalità “TESTA distaccata”).

Date queste due correnti trasversali, penso che la vera risposta al “perché”, a questo punto, sia “nessuno si preoccupa abbastanza di aggiungerlo”. 🙂 L’argomento privacy è valido, ma non c’è motivo per cui git clone non possa controllare un commit per ID dopo la clonazione, così come si può dire di controllare qualche ramo diverso da master 3 con git clone -b ... . L’unico svantaggio di consentire -b sha1 è che Git non può controllare frontalmente (prima che inizi il processo di clonazione) se verrà ricevuto sha1 . Può controllare i nomi di riferimento, dal momento che quelli sono trasferiti (insieme ai loro consigli di ramo o altri valori SHA-1) in primo piano, quindi git clone -b nonexistentbranch ssh://... termina rapidamente e non crea la copia:

 fatal: Remote branch nonexistentbranch not found in upstream origin fatal: The remote end hung up unexpectedly 

Se -b permesso un ID, otterresti l’intero clone, quindi dovrebbe dirti: “oh dio, scusa, non posso controllare quell’ID, ti lascio al master invece” o qualsiasi altra cosa. (Che è più o meno quello che succede ora con un sottomodulo rotto.)


1 Mentre git upload-archive ora applica questa regola di “privacy”, non è sempre stato così (è stato introdotto nella versione 1.7.8.1); e molti (la maggior parte?) server git-web, incluso quello distribuito con Git stesso, consentono la visualizzazione tramite ID arbitrario. Questo è probabilmente il motivo per cui allowUnreachable stato aggiunto upload-archive di upload-archive alcuni anni dopo che è stato aggiunto il codice “only by ref name” (ma si noti che le versioni di Git dopo 1.7.8 e precedenti alla 2.0.0 non hanno modo di allentare le regole). Quindi, mentre l’idea di “sicurezza” è valida, c’è stato un periodo (pre 1.7.8.1) quando non è stato applicato.

2 Esistono numerosi modi per “filtrare” dati apparentemente privati ​​da un repository Git. Un nuovo file, Documentation / transfer-data-leaks , sta per apparire in Git 2.11.1, mentre Git 2.11.0 ha aggiunto alcune funzionalità interne (vedi commit 722ff7f87 tra gli altri) per rilasciare immediatamente oggetti spinti ma non accettati. Tali oggetti vengono alla fine raccolti dalla spazzatura, ma rimangono esposti per la durata.

3 In realtà, per impostazione predefinita git clone esegue un check-out locale del ramo che pensa sia HEAD riferimento HEAD del telecomando. Di solito è comunque master .

La clonazione di un repository è un’operazione diversa dalla verifica. Non si “clona un commit specifico”. Per comodità è ansible clonare e quindi eseguire il checkout di un particolare ramo preesistente allo stesso tempo, poiché è ciò che la maggior parte delle persone desidera. Se questo non soddisfa le tue esigenze (nessun ramo per il particolare SHA che desideri) usa o alias qualche forma di

 git clone -n  && cd  && git checkout SHA 

Come le altre risposte dicono, questo non è in genere un problema, ma non dicono perché non è ansible clonare un commit specifico. La risposta è sicurezza.

Se si inviano accidentalmente informazioni riservate e quindi si forza forzatamente una cronologia fissa, i commit con le informazioni riservate verranno comunque memorizzati sul server, fino a quando il garbage collector di Git del server non troverà più la necessità. Se l’hash è noto (potrebbe essere ad esempio disponibile nei log), un utente malintenzionato potrebbe richiedere il commit specifico che non avrebbe dovuto essere spinto, anche se fosse ansible verificare che quando si forzasse la cronologia fissa, nessuno aveva già recuperato quei commit.

Assicurandosi di poter clonare solo da refs, si assicura che solo i commit “raggiungibili” vengano inviati ai client.

Se il tuo commit specifico è referenziato da un ramo, puoi fare un:

 git clone -b yourBranch /url/of/the/repo 

Il repository clonato sarà direttamente al commit referenziato da quel ramo.