Ecco cosa non mi piace di git:
Prima di tutto, penso che l'idea distribuita vada contro la realtà. Chiunque stia effettivamente usando git lo fa in modo centralizzato, anche Linus Torvalds. Se il kernel fosse gestito in modo distribuito, ciò significherebbe che non potrei effettivamente scaricare i sorgenti "ufficiali" del kernel - non ce ne sarebbero uno - dovrei decidere se voglio la versione di Linus, o quella di Joe, o la versione di Bill. Sarebbe ovviamente ridicolo, ed è per questo che esiste una definizione ufficiale che Linus controlla utilizzando un flusso di lavoro centralizzato.
Se accetti di volere una definizione centralizzata delle tue cose, diventa chiaro che i ruoli del server e del client sono completamente diversi, quindi il dogma secondo cui i software client e server dovrebbero essere gli stessi diventa puramente limitante. Il dogma che i dati del client e del server dovrebbero essere gli stessi diventa palesemente ridicolo, specialmente in una base di codice che ha quindici anni di storia di cui nessuno si preoccupa ma che tutti dovrebbero clonare.
Quello che vogliamo davvero fare con tutte quelle vecchie cose è metterle in un armadio e dimenticare che sono lì, proprio come fa qualsiasi normale VCS. Il fatto che git trascini tutto avanti e indietro sulla rete ogni giorno è molto pericoloso, perché ti tormenta a potarlo. Quella potatura comporta molte decisioni noiose e può andare storta. Quindi le persone probabilmente manterranno un'intera serie di repo di istantanee da vari punti della storia, ma non era questo ciò a cui serviva il controllo del codice sorgente? Questo problema non esisteva fino a quando qualcuno non ha inventato il modello distribuito.
Git incoraggia attivamente le persone a riscrivere la storia, e quanto sopra è probabilmente una delle ragioni per questo. Ogni normale VCS rende la riscrittura della cronologia impossibile per tutti tranne che per gli amministratori e si assicura che gli amministratori non abbiano motivo di prenderla in considerazione. Correggimi se sbaglio, ma per quanto ne so, git non fornisce alcun modo per concedere agli utenti normali l'accesso in scrittura ma proibisce loro di riscrivere la cronologia. Ciò significa che qualsiasi sviluppatore con rancore (o che stava ancora lottando con la curva di apprendimento) potrebbe distruggere l'intera base di codice. Come lo stringiamo? Bene, o fai backup regolari dell'intera cronologia, cioè mantieni la cronologia al quadrato, o proibisci l'accesso in scrittura a tutti tranne che a qualche poveraccio che riceverebbe tutte le differenze via e-mail e le unirebbe a mano.
Facciamo un esempio di un grande progetto ben finanziato e vediamo come git sta funzionando per loro: Android. Una volta ho deciso di giocare con il sistema Android stesso. Ho scoperto che avrei dovuto usare un gruppo di script chiamati repo per ottenere il loro git. Alcuni repo vengono eseguiti sul client e altri sul server, ma entrambi, per la loro stessa esistenza, stanno illustrando il fatto che git è incompleto in entrambe le capacità. Quello che è successo è che non sono stato in grado di estrarre le fonti per circa una settimana e poi ho rinunciato del tutto. Avrei dovuto estrarre una quantità davvero enorme di dati da diversi repository diversi, ma il server era completamente sovraccarico di persone come me. Il repository era scaduto e non è stato possibile riprenderlo dal punto in cui era scaduto. Se git è così distribuibile, avresti pensato che ' Ho fatto una sorta di operazione peer-to-peer per alleviare il carico su quell'unico server. Git è distribuibile, ma non è un server. Git + repo è un server, ma il repo non è distribuibile perché è solo una raccolta ad-hoc di hack.
Un esempio simile dell'inadeguatezza di git è gitolite (e il suo antenato che apparentemente non ha funzionato così bene). Gitolite descrive il suo lavoro come facilitare la distribuzione di un server git. Di nuovo, l'esistenza stessa di questa cosa prova che git non è un server, non più di quanto non sia un client. Inoltre, non lo sarà mai, perché se diventasse uno dei due tradirebbe i suoi principi fondanti.
Anche se credessi nella cosa distribuita, git sarebbe comunque un disastro. Che cos'è, ad esempio, una filiale? Dicono che tu crei implicitamente un ramo ogni volta che cloni un repository, ma non può essere la stessa cosa di un ramo in un singolo repository. Quindi ci sono almeno due cose diverse che vengono chiamate rami. Ma poi, puoi anche riavvolgere in un repository e iniziare a modificare. È come il secondo tipo di ramo o di nuovo qualcosa di diverso? Forse dipende dal tipo di repo che hai - oh sì - a quanto pare nemmeno il repo è un concetto molto chiaro. Ci sono quelli normali e quelli spogli. Non è possibile passare a uno normale perché la parte nuda potrebbe non essere sincronizzata con il suo albero dei sorgenti. Ma non puoi importare in uno nudo perché non ci hanno pensato. Quindi devi cvsimportare in uno normale, clonalo su uno nudo che gli sviluppatori hanno colpito, e cvsexport quello su una copia di lavoro cvs che deve ancora essere archiviata in cvs. Chi può essere infastidito? Da dove vengono tutte queste complicazioni? Dall'idea distribuita stessa. Alla fine ho abbandonato la gitolite perché mi imponeva ancora di più di queste restrizioni.
Git dice che la ramificazione dovrebbe essere leggera, ma molte aziende hanno già un serio problema con le filiali canaglia, quindi avrei pensato che la ramificazione dovrebbe essere una decisione importante con una rigorosa polizia. È qui che per forza brilla davvero ...
In definitiva, raramente hai bisogno di branch perché puoi destreggiarti tra i changeset in modo molto agile. Ad esempio, il normale flusso di lavoro prevede la sincronizzazione con l'ultima versione valida nota sulla linea principale, quindi si scrive la funzione. Ogni volta che provi a modificare un file, il diff di quel file viene aggiunto al tuo "changeset predefinito". Quando provi a fare il check-in del changeset, esso cerca automaticamente di unire le notizie dalla mainline al tuo changeset (ribasandolo efficacemente) e poi esegue il commit. Questo flusso di lavoro viene applicato senza che tu debba nemmeno capirlo. Mainline raccoglie quindi una cronologia delle modifiche che puoi facilmente scegliere in seguito. Ad esempio, supponi di voler ripristinare uno vecchio, diciamo, quello prima di quello prima dell'ultimo. Ti sincronizzi con il momento prima della modifica incriminata, contrassegni i file interessati come parte del changeset, sincronizza con il momento successivo e unisci con "sempre mio". (C'era qualcosa di molto interessante qui: la sincronizzazione non significa avere la stessa cosa - se un file è modificabile (cioè in un changeset attivo) non verrà bloccato dalla sincronizzazione ma contrassegnato come dovuto per la risoluzione.) Ora hai una lista delle modifiche che annulla quella incriminata. Unisciti alle notizie successive e avrai una lista delle modifiche che puoi posizionare sopra la linea principale per avere l'effetto desiderato. In nessun momento abbiamo riscritto la storia. Unisciti alle notizie successive e avrai una lista delle modifiche che puoi posizionare sopra la linea principale per avere l'effetto desiderato. In nessun momento abbiamo riscritto la storia. Unisciti alle notizie successive e avrai una lista delle modifiche che puoi posizionare sopra la linea principale per avere l'effetto desiderato. In nessun momento abbiamo riscritto la storia.
Ora, supponendo a metà di questo processo, qualcuno ti corre incontro e ti dice di mollare tutto e correggere qualche bug. Devi solo dare un nome alla tua lista modifiche predefinita (un numero in realtà) quindi "sospenderla", correggere il bug nella lista modifiche predefinita ora vuota, eseguirne il commit e riprendere la lista modifiche denominata. È tipico avere diversi elenchi di modifiche sospesi in un momento in cui provi cose diverse. È facile e privato. Ottieni ciò che vuoi veramente da un regime di filiale senza la tentazione di procrastinare o di tirarti indietro dalla fusione con la linea principale.
Suppongo che sarebbe teoricamente possibile fare qualcosa di simile in git, ma git rende praticamente qualsiasi cosa possibile piuttosto che affermare un flusso di lavoro che approviamo. Il modello centralizzato è un insieme di valide semplificazioni relative al modello distribuito che è una generalizzazione non valida. È così generalizzato che in pratica si aspetta che tu implementi il controllo del codice sopra di esso, come fa il repo.
L'altra cosa è la replica. In git, tutto è possibile quindi devi capirlo da solo. In definitiva, ottieni una cache effettivamente senza stato. L'unica configurazione che deve sapere è dove si trova il master ei client possono puntare al master o alla cache a loro discrezione. È un lavoro di cinque minuti e non può andare storto.
Hai anche trigger e moduli personalizzabili per affermare revisioni del codice, riferimenti a bugzilla ecc.E, naturalmente, hai rami per quando ne hai effettivamente bisogno. Non è chiaro, ma è vicino ed è estremamente facile da configurare e mantenere.
Tutto sommato, penso che se sai che lavorerai in modo centralizzato, cosa che fanno tutti, potresti anche usare uno strumento progettato pensando a questo. Git è sopravvalutato a causa della temibile arguzia di Linus insieme alla tendenza delle persone a seguirsi l'un l'altro come pecore, ma la sua principale ragion d'essere in realtà non regge il buon senso e, seguendolo, git lega le proprie mani con i due enormi dogmi che (a) il software e (b) i dati devono essere gli stessi sia sul client che sul server, e questo renderà sempre complicato e zoppo il lavoro centralizzato.