Idiota
Questa risposta include GitHub come molte persone hanno chiesto anche a questo proposito.
Archivi locali
Git (localmente) ha una directory ( .git
) in cui si impegnano i file e questo è il 'repository locale'. Ciò è diverso dai sistemi come SVN in cui si aggiunge e si impegna immediatamente nel repository remoto.
Git memorizza ogni versione di un file che cambia salvando l'intero file. A questo proposito è anche diverso da SVN in quanto potresti passare a qualsiasi versione individuale senza "ricrearla" attraverso modifiche delta.
Git non "blocca" i file e quindi evita la funzionalità di "blocco esclusivo" per una modifica (vengono in mente sistemi più vecchi come pvcs), quindi tutti i file possono sempre essere modificati, anche quando non in linea. In realtà fa un ottimo lavoro di unire le modifiche ai file (all'interno dello stesso file!) Durante pull o fetch / push in un repository remoto come GitHub. L'unica volta che è necessario apportare modifiche manuali (in realtà modificando un file) è se due modifiche coinvolgono le stesse righe di codice.
filiali
I rami ti consentono di conservare il codice principale (il ramo "principale"), fare una copia (un nuovo ramo) e quindi lavorare all'interno di quel nuovo ramo. Se il lavoro richiede un po 'di tempo o il master riceve molti aggiornamenti da quando è stato creato il ramo, è necessario eseguire l'unione o la riformulazione (spesso preferita per una cronologia migliore e conflitti più facili da risolvere) con il ramo principale. Al termine, unisci le modifiche apportate nel ramo al repository principale. Molte organizzazioni utilizzano i rami per ogni lavoro, sia esso una caratteristica, un bug o un lavoro di routine. Altre organizzazioni utilizzano le filiali solo per modifiche importanti come gli aggiornamenti di versione.
Fork: con un branch controlli e gestisci il branch, mentre con un fork qualcun altro controlla di accettare il codice.
In generale, ci sono due approcci principali per fare rami. Il primo è mantenere la maggior parte delle modifiche sul ramo principale, usando solo i rami per cose più grandi e più lunghe come le modifiche di versione in cui si desidera avere due rami disponibili per esigenze diverse. Il secondo è quello in cui fondamentalmente crei un ramo per ogni richiesta di funzione, correzione di bug o lavoro di routine e poi decidi manualmente quando unire effettivamente quei rami nel ramo principale principale. Anche se questo sembra noioso, questo è un approccio comune ed è quello che attualmente uso e raccomando perché questo mantiene il ramo principale più pulito ed è il maestro che promuoviamo per la produzione, quindi vogliamo solo codice completo, testato, tramite il rebasing e fusione di rami.
Il modo standard per portare un ramo 'in' al master è fare un merge
. Le filiali possono anche essere "ridisegnate" per "ripulire" la storia. Non influisce sullo stato corrente e viene fatto per fornire una cronologia "più pulita".
Fondamentalmente, l'idea è che ti sei ramificato da un certo punto (di solito dal maestro). Da quando ti sei ramificato, lo stesso "maestro" da allora si è spostato in avanti da quel punto di diramazione. Sarà "più pulito" (più facile da risolvere i problemi e la cronologia sarà più facile da capire) se tutte le modifiche che hai fatto in un ramo sono giocate contro lo stato attuale del master con tutte le sue ultime modifiche. Quindi, il processo è: salvare le modifiche; ottenere il 'nuovo' master e quindi riapplicare (questa è la parte rebase) le modifiche di nuovo rispetto a ciò. Ricorda che rebase, proprio come l'unione, può provocare conflitti che devi risolvere manualmente (ad es. Modifica e correzione).
Una linea guida da notare:
rifare solo se il ramo è locale e non lo hai ancora inviato al telecomando!
Ciò è dovuto principalmente al fatto che il rifacimento può alterare la storia che altre persone vedono e che può includere i propri impegni.
Tracciamento dei rami
Questi sono i rami che sono chiamati origin/branch_name
(al contrario di giusto branch_name
). Quando si spinge e si estrae il codice da / verso repository remoti, questo è in realtà il meccanismo attraverso il quale ciò accade. Ad esempio, quando si git push
chiama un ramo building_groups
, il ramo passa prima a origin/building_groups
e poi al repository remoto. Allo stesso modo, se si esegue un git fetch building_groups
, il file recuperato viene inserito nel origin/building_groups
ramo. Puoi quindi scegliere di unire questo ramo nella tua copia locale. La nostra pratica è di fare sempre una git fetch
fusione manuale piuttosto che solo una git pull
(che fa entrambe le precedenti in un solo passaggio).
Recupero di nuovi rami.
Ottenere nuovi rami: nel punto iniziale di un clone avrai tutti i rami. Tuttavia, se altri sviluppatori aggiungono rami e li spingono sul telecomando, deve esserci un modo per "conoscere" quei rami e i loro nomi per poterli abbattere localmente. Questo viene fatto tramite un git fetch
che porterà tutti i rami nuovi e modificati nel repository locale usando i rami di tracciamento (ad es origin/
.). Una volta fetch
ed, è possibile git branch --remote
elencare i rami di tracciamento e git checkout [branch]
passare a uno qualsiasi.
Fusione
L'unione è il processo di combinazione delle modifiche al codice da rami diversi o da versioni diverse dello stesso ramo (ad esempio quando un ramo locale e un telecomando non sono sincronizzati). Se uno ha sviluppato lavoro in un ramo e il lavoro è completo, pronto e testato, allora può essere unito al master
ramo. Questo viene fatto git checkout master
per passare al master
ramo, quindi git merge your_branch
. L'unione riunirà tutti i diversi file e anche diverse modifiche negli stessi file . Ciò significa che cambierà effettivamente il codice all'interno dei file per unire tutte le modifiche.
Quando si fa il checkout
di master
è anche consigliato di fare una git pull origin master
per ottenere la versione più recente del maestro a distanza fuse in tuo padrone locale. Se il master remoto è cambiato, cioè moved forward
vedrai informazioni che riflettono ciò durante quello git pull
. Se questo è il caso (master modificato), ti viene consigliato git checkout your_branch
e quindi rebase
master, in modo che le tue modifiche vengano effettivamente "riprodotte" in cima al "nuovo" master. Quindi si continuerà ad aggiornare Master come mostrato nel paragrafo successivo.
Se non ci sono conflitti, al master verranno aggiunte le nuove modifiche. Se ci sono conflitti, ciò significa che gli stessi file hanno modifiche attorno a righe di codice simili che non possono unire automaticamente. In questo caso git merge new_branch
segnalerà la presenza di conflitti da risolvere. Li 'risolvi' modificando i file (che avranno entrambe le modifiche), selezionando le modifiche che desideri, eliminando letteralmente le righe delle modifiche che non desideri e quindi salvando il file. Le modifiche sono contrassegnate con separatori come ========
e <<<<<<<<
.
Una volta risolti eventuali conflitti, lo farai di nuovo git add
e git commit
tali modifiche continueranno a fondersi (riceverai feedback da Git durante questo processo per guidarti).
Quando il processo non funziona bene, troverai git merge --abort
molto utile ripristinare le cose.
Rinnovo interattivo e compressione / riordino / rimozione di commit
Se hai lavorato in molti piccoli passaggi, ad esempio, impegni il codice come "work-in-progress" ogni giorno, potresti voler "schiacciare" quei piccoli piccoli commit in alcuni commit più grandi. Ciò può essere particolarmente utile quando si desidera eseguire revisioni del codice con i colleghi. Non vuoi ripetere tutti i 'passaggi' che hai fatto (tramite commit), vuoi solo dire che qui è l'effetto finale (diff) di tutte le mie modifiche per questo lavoro in un unico commit.
Il fattore chiave da valutare quando si considera se fare questo è se i commit multipli sono contro lo stesso file o più file più di una volta (in questo caso è meglio eseguire i commit di compressione). Questo viene fatto con lo strumento di rebasing interattivo. Questo strumento ti consente di eliminare i commit, eliminare i commit, riformulare i messaggi, ecc. Ad esempio, git rebase -i HEAD~10
( nota: che è a ~
, non a-
) fa apparire quanto segue:
Fai attenzione però e usa questo strumento "con cautela". Esegui uno squash / elimina / riordina alla volta, esci e salva quel commit, quindi rientra nello strumento. Se i commit non sono contigui, puoi riordinarli (e quindi schiacciarli se necessario). Puoi effettivamente eliminare anche i commit qui, ma devi davvero essere sicuro di quello che stai facendo quando lo fai!
forchette
Esistono due approcci principali alla collaborazione nei repository Git. Il primo, dettagliato sopra, è direttamente tramite i rami che le persone tirano e spingono da / a. Questi collaboratori hanno le loro chiavi SSH registrate nel repository remoto. Ciò consentirà loro di spingere direttamente verso quel repository. Il rovescio della medaglia è che devi mantenere l'elenco degli utenti. L'altro approccio, il fork, consente a chiunque di "fork" il repository, fondamentalmente facendo una copia locale nel proprio account repository Git. Possono quindi apportare modifiche e, una volta terminato, inviare una 'richiesta pull' (in realtà è più una 'spinta' da loro e una richiesta 'pull' per l'effettivo manutentore del repository) per ottenere il codice accettato.
Questo secondo metodo, utilizzando forks, non richiede a qualcuno di mantenere un elenco di utenti per il repository.
GitHub
GitHub (un repository remoto) è una sorgente remota che normalmente si spinge e si tira su quelle modifiche commesse se si dispone (o si aggiunge a) un tale repository, quindi locale e remoto sono in realtà abbastanza distinti. Un altro modo di pensare a un repository remoto è che è una .git
struttura di directory che vive su un server remoto.
Quando si 'fork' - nella GUI del browser Web GitHub è possibile fare clic su questo pulsante - si crea una copia ('clone') del codice nel proprio account GitHub. Può essere un po 'sottile la prima volta che lo fai, quindi assicurati di guardare in quale repository è elencata una base di codice - o il proprietario originale o "biforcuto" e tu, ad esempio, in questo modo:
Una volta che hai la copia locale, puoi apportare le modifiche che desideri (tirandole e spingendole su un computer locale). Quando hai finito, invia una "richiesta pull" al proprietario / amministratore del repository originale (sembra fantasioso, ma in realtà fai semplicemente clic su questo:) e lo "inseriscono".
Più comune per un team che lavora insieme sul codice è "clonare" il repository (fare clic sull'icona "copia" nella schermata principale del repository). Quindi, digitare git clone
e incollare localmente . Questo ti installerà localmente e puoi anche spingere e tirare nella posizione (condivisa) di GitHub.
cloni
Come indicato nella sezione su GitHub, un clone è una copia di un repository. Quando si dispone di un repository remoto, si emette il git clone
comando sull'URL e si finisce con una copia locale o clone del repository. Questo clone ha tutto , i file, il ramo principale, gli altri rami, tutti i commit esistenti, l'intero shebang. È questo clone che fai i tuoi add-on e si impegna e quindi il repository remoto stesso è ciò a cui spingi quei commit. È questo concetto locale / remoto che rende Git (e sistemi simili ad esso come Mercurial) un DVCS ( Distributed Version Control System) al contrario dei CVS più tradizionali (Code Versioning Systems) come SVN, PVCS, CVS, ecc. Dove ti impegni direttamente nel repository remoto.
visualizzazione
È possibile visualizzare la visualizzazione dei concetti chiave
http://marklodato.github.com/visual-git-guide/index-en.html e
http://ndpsoftware.com/git-cheatsheet.html#loc=index
Se desideri una visualizzazione visiva del funzionamento delle modifiche, non puoi battere lo strumento visivo gitg
( gitx
per macOS) con una GUI che chiamo "la mappa della metropolitana" (in particolare London Underground), ottima per mostrare chi ha fatto cosa, come le cose cambiano, divergono e si fondono, ecc.
Puoi anche usarlo per aggiungere, eseguire il commit e gestire le tue modifiche!
Sebbene gitg / gitx sia abbastanza minimo, il numero di strumenti della GUI continua ad espandersi. Molti utenti Mac usano il fork di gitx di Brotherbard e per Linux, un'ottima opzione è smart-git con un'interfaccia intuitiva ma potente:
Nota che anche con uno strumento GUI, probabilmente eseguirai molti comandi dalla riga di comando.
Per questo, ho i seguenti alias nel mio ~/.bash_aliases
file (che viene chiamato dal mio ~/.bashrc
file per ogni sessione terminale):
# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '
E ho i seguenti "alias git" nel mio ~/.gitconfig
file - perché questi?
Quindi il completamento del ramo (con il tasto TAB) funziona!
Quindi questi sono:
[alias]
co = checkout
cob = checkout -b
Esempio di utilizzo: git co [branch]
<- il completamento della scheda per i rami funzionerà.
Strumento di apprendimento della GUI
È possibile che https://learngitbranching.js.org/ sia utile per apprendere alcuni dei concetti di base. Schermata:
Video: https://youtu.be/23JqqcLPss0
Finalmente 7 salvavita chiave!
Apporti le modifiche, le aggiungi e le impegni (ma non spingere) e poi oh! ti rendi conto di essere padrone!
git reset [filename(s)]
git checkout -b [name_for_a_new_branch]
git add [file(s)]
git commit -m "A useful message"
Voila! You've moved that 'master' commit to its own branch !
Si incasinano alcuni file mentre si lavora in una filiale locale e si desidera semplicemente tornare a ciò che si è verificato l'ultima volta che si è eseguito un git pull
:
git reset --hard origin/master # You will need to be comfortable doing this!
Inizi a fare modifiche localmente, modifichi mezza dozzina di file e poi, oh merda, sei ancora nel ramo principale (o in un altro):
git checkout -b new_branch_name # just create a new branch
git add . # add the changes files
git commit -m"your message" # and commit them
Hai incasinato un particolare file nel tuo ramo corrente e vuoi sostanzialmente "resettare" quel file (perdere le modifiche) su come è stato l'ultima volta che l'hai estratto dal repository remoto:
git checkout your/directories/filename
Questo in realtà reimposta il file (come molti comandi Git non è ben chiamato per quello che sta facendo qui).
Apporti alcune modifiche localmente, vuoi assicurarti di non perderle mentre fai un git reset
o rebase
: faccio spesso una copia manuale dell'intero progetto ( cp -r ../my_project ~/
) quando non sono sicuro se potrei sbagliare in Git o perdere importanti i cambiamenti.
Stai ribassando ma le cose si incasinano:
git rebase --abort # To abandon interactive rebase and merge issues
Aggiungi il tuo ramo Git al tuo PS1
prompt (vedi https://unix.stackexchange.com/a/127800/10043 ), ad es.
Il ramo è selenium_rspec_conversion
.