CSharp:Source Control - Git operazioni tipiche
From Aino Wiki
Schema di scenario tipico
Doc:
- aulab.it
- Guida con scenari: get-git.readthedocs.io
Contents
Basi
Termini:
-
Object Database
, è il database chiave/valore conservato nella cartella nascosta .git. la chiave è un valore calcolato in SHA1, il valore è il contenuto del file. - il
file system
è la directory con i files. - il
repository
è il database locale su file che conserva i vari commit -
staging area
oindex
, fa da tramite tra il file system ed il repository. E' uno spazio dove parcheggiare gli oggetti pronti per il prossimo commit mediante il quale finiranno nel repository. - il
remote
repository è un repository su altro computer col quale si può chiedere che lui si allinei al nostro contenuto o ci si può allinearsi al suo i comandi a disposizione per farlo sono rispettivamente:push
efetch
.
Ramificazioni - Branch:
Se l'oggetto del versioning è il codice sorgente (ciò non esclude altre risorse) generalmente si usano due rami ovvero branch di riferimento:
- il master che è creato di default e costituisce la versione ufficiale del repository;
- il develop che con Git standard va creato esplicitamente, sarà la versione parallela soggetta a modifiche frequenti perché vi confluiscono tutte le nuove funzionalità da consolidare.
Si crea il ramo develop (ricopiandoci il master o origin):
git branch develop git push -u origin develop
Esiste un comando che fa questo ed altro in modo interattivo:
git flow init
controllerà l’esistenza dei rami master e develop per noi e li creerà automaticamente nel caso non ci fossero.
Tools
Per il sistema operativo Windows:
- Git CMD, è un prompt comandi DOS ma che è collegato a funzionalità Git quindi è usato per gestire da "Terminale" (linea comando) un repository Git mediante i comandi spiegati qui sotto.
- Git GUI, è una Windows application quindi una GUI per lavorare con un repository Git.
- Git Bash, simile a Git CMD ma che ricorda un terminale Linux, appunto Bash, serve a gestire archivi Git sul file system.
- Gitk, è una Windows application quindi una GUI che serve a visualizzare\gestire i commit di Git anche quelli "nascosti". Si può lanciare da Git CMD (es.
gitk
o per visualizzare anche quelli nascostigitk --all
)
Comandi consueti
Per Git versione Windows:
Comando___Git | Descrizione___________________________ | Es. |
---|---|---|
git init | Inizializzazione del repository. Da lanciare nella cartella del progetto da gestire |
|
git add | Ufficializza l'aggiunta dei nuovi files nell'indice dei files da gestire, i files sono aggiunti alla staging area |
|
git commit | Rende definitive le modifiche aggiunndo un commento che le gescrive e che vale per l'intero insieme di modifiche | git commit -m "Prima versione del progetto" |
git log | Per avere l'elenco cronologico di tutti i commit |
|
git diff | mostra le differenze tra l’attuale contenuto della staging area e l’ultimo commit | git diff --staged |
git stash | serve per mettere da parte tutte le attuali modifiche non committate, per recuperarle in un secondo momento. |
|
git tag -a <TAG_NAME> | Per marchiare un intero set di files, fotografia corrente del progetto, con un codice di versione al quale riferirvisi nel complessivo, è un segnalibro. | git tag v1.1.0 -m "tagging version 1.1.0"
|
git amend | è una scorciatoia che ci permette di unire nuove modifiche presenti nella staging area all’ultimo commit appena salvato, prima va fatto l'add delle novità aggiunte.
L’opzione –no-edit che istruisce Git a mantenere l’esistente messaggio di commit. |
git commit --amend --no-edit
|
git push | Per pubblicare le modifiche sul server remoto. (manuale) Ovviamente logicamente deve esser stato affettuato l'eventuale add e commit precedente + associazione col repository remoto.
|
NOTA Per capire cosa scrivere dopo "push" aprire il file |
git fetch | Per prelevare da Git (locale o remoto) sovrascrivendo i file locali, quindi ignorando tutte le modifiche locali |
oppure
|
git status | Mostra lo stato attuale del repository, indicando i file modificati, eliminati o aggiunti | . |
git remote | Per lavorare con un repository remoto quindi collegare il locale con uno specifico remoto indicando a git il suo indirizzo. NOTA si possono avere più repository remoti per uno stesso progetto locale. |
|
git checkout | Serve per tornare indietro ad un precedente commit. Occorre però conoscere l'ID del commit e lo si fa mediante il comando git log --oneline che restituirà un elenco tabellare in cui la prima colonna indicherà il codice ID ad es. 43474fb Per rendere più comodo l'identificazione del commit voluto anche tra quelli non visibili usare gitk --allNOTA che l'Id in realtà è un puntatore. |
git checkout 43474fb
|
git branch | Per impostare un branch. Un branch in realtà è una etichetta assegnata ad un Commit per facilitare il riferimento in eventuali checkout ovvero cambi di "contesto". A proposito si usa un segnaposto " |
|
git clone | Per prelevare il contenuto di un determinato progetto remoto. Successivamente, per aggiornare il progetto locale (a meno di modifiche locali successive) si potrà usare |
git clone http://GitUser1@git.myserver.com/Git_IIS/ProgettoTest01.git CartellaLocale #Copia via HTTP il ProgettoTest01 dal server remoto "git.myserver.com" usando lo user "GitUser1" e lo mette nella cartella locale "CartellaLocale"
|
git pull | Per prelevare tutte le modifiche da un progetto già collegato (per cui s'è già eseguito il CLONE). NOTA andare dentro la cartella del progetto e lanciare il comando |
NOTA per capire cosa scrivere dopo "pull" aprire il file |
git config
|
Per impostare informazioni di configurazione locali o globali di Git. NOTA per poter committare qualcosa occorre impostare l'utente corrente! |
|
NOTA
- Eventuali cartelle vuote NON verranno aggiunte o committate, occorre che abbiamo almeno un file.
Esempi
Configurazione
Il primo step è quello di inizializzare il repository considerato remoto e questo si fa mediante il comando git init
. L'inizializzazione riguarda la cartella con l'archivio che potrà sia esser già esistente che non esistere, nel primo caso il comando git init
si lancerà nella cartella creata e nel secondo si lancerà nella cartella superiore e si indicherà il nome del repository che poi sarà anche il nome della cartella.
La configurazione di un repository è in un file di configurazione che è in una versione locale e remota.
Es Cfg locale
Segue il file di configurazione (.\.git\config
) per un repository locale:
- che è collegato ad un repository remoto chaimato "foobar".
- è ti tipo locale quindi "non-bare".
- ha tre branch: "master", "experiment" e "Ultimo1".
[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true ignorecase = true [remote "foobar"] url = http://GitUser1@SPXMIW3658/Git_IIS/repo-remoto fetch = +refs/heads/*:refs/remotes/foobar/* [branch "master"] remote = foobar merge = refs/heads/master [branch "experiment"] remote = foobar merge = refs/heads/experiment [branch "Ultimo1"] remote = foobar merge = refs/heads/Ultimo1
Es Cfg remoto
Un file di configurazione remoto, .\.git\config
, potrebbe esser così (non-bare repository):
[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true ignorecase = true [receive] denyCurrentBranch = ignore
Repository locale
Es definizione repository locale 1
Per iniziare con un repository da gestire col servizio Git si può partire usando i segeunti comandi:
D:\temp\testGit> md ProgettoTest01.git D:\temp\testGit> cd ProgettoTest01.git D:\temp\testGit\ProgettoTest01.git> git init D:\temp\testGit\ProgettoTest01.git> git add . D:\temp\testGit\ProgettoTest01.git> git commit -m "Contenuto di partenza" D:\temp\testGit\ProgettoTest01.git> git log
Ora su un PC client si può già scaricare il repository di ProgettoTest01.git, ma la working directory sarà vuota.
Aggiungere un file, "PrimoFile.txt":
D:\temp\testGit\ProgettoTest01.git> git add PrimoFile.txt D:\temp\testGit\ProgettoTest01.git> git commit -m "Primo file" D:\temp\testGit\ProgettoTest01.git> git log
Es Commit con Add e Remove
Invece di fare un Add e poi un Commit o fare un Remove e Commit finale, c'è il seguente comando comodo:
git commit -am "Commit genrico purificato da file cancellati e aggiornato con integrazione e modifiche"
PS per rimuvare file: git rm file\_name
Es Creazione ed uso di Branch
Un branch crea una etichetta ad un commit Supponendo dia vere la seguente situazione:
Si crea il seguente Branch chiamandolo "Br_Secondo"
git branch Br_Secondo 9c82359
Quindi per usarlo ovvero per cambiare barnch si usa il comando checkout
:
git checkout Br_Secondo
Per tornare sul set principale del progetto occorre spostarsi sul "master" (che è il principale dei branch!):
git checkout master
Per visualizzare le modifiche tra 2 branch si usa diff
:
git diff Br_Secondo master
Nota "master" è banalmente un brach che c'è sempre
Interazioni remote
Es Creazione remote bare repository 1
Esempio di creazione di un repository centralizzato su un server e due PC client A e B.
Supponendo di essere sul server remoto XXX su cui si è già configurato Git per lavorare come applicazione Web (quindi nel caso IIS è associato alla cartella D:\Git_Repository\Git_IIS
( guida interna). Supponendo che sul server ancora non ci sia nulla da archiviare.
Si crea il "bare repository" usando Git CMD:
git init --bare repo-remoto
che produrrà la cartella "repo-remoto" sul File System e che prima non c'era:
Ora si popolerà il repository remoto con dei contenuti quindi un progetto già esistente e controllato mediante Git. Supponiamo che tale repository sia su un PC client, PC A, e nella cartella F:\Git_TestLocal\progetto
.
Si associa il repository locale al repository remoto dando un nome in alias "foobar", supponiamo anche che si adotti la "basic authentication" quindi sul server XXX ci sia un utente di sistema operativo chiamato 'GitUser1'.
git remote add foobar http://GitUser1@XXX/Git_IIS/repo-remoto
Il comando precedente ha aggiornato il file ".git\config" sul PC A.
Quindi ora si può popolare il repository remoto con un camando push
mediante Git CMD:
git push foobar master
con questo output di esempio:
L'effetto sarà quello per cui la cartella "objects" si riempirà di sottocartelle prima non esistenti che si aggiungono alle due: "info" e "pack".
A questo punto si testa tutto andando su un altro PC client, il PC B, e si lancia il comando clone
del repository remoto su XXX:
git clone http://GitUser1@XXX/Git_IIS/repo-remoto
che produrra' il seguente output:
Si verificherà la creazione locale della cartella progetto
con gli stessi file della cartella del primo PC.
Se si è configurato IIS come interfaccia WEB sul server Remoto, un log di IIS può essere (si riporta come esempio, non si legge il nome della Web App ma il MAC della scheda di rete):
#Software: Microsoft Internet Information Services 10.0 #Version: 1.0 #Date: 2024-09-04 09:45:46 #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken 2024-09-04 09:45:46 fe80::6249:2830:b534:a3f8%12 GET /Git_IIS/repo-remoto/info/refs service=git-upload-pack 80 - fe80::6249:2830:b534:a3f8%12 git/2.44.0.windows.1 - 401 2 5 3 2024-09-04 09:45:46 fe80::6249:2830:b534:a3f8%12 GET /Git_IIS/repo-remoto/info/refs service=git-upload-pack 80 GitUser1 fe80::6249:2830:b534:a3f8%12 git/2.44.0.windows.1 - 401 1 1326 5 2024-09-04 09:45:48 fe80::6249:2830:b534:a3f8%12 HEAD / - 80 - fe80::6249:2830:b534:a3f8%12 Git-Credential-Manager/2.4.1.0+(Windows;+x86-64)+CLR/.NET+Framework+4.8.9261.0 - 200 0 0 1355 2024-09-04 09:46:07 fe80::6249:2830:b534:a3f8%12 GET /Git_IIS/repo-remoto/info/refs service=git-upload-pack 80 GitUser1 fe80::6249:2830:b534:a3f8%12 git/2.44.0.windows.1 - 200 0 0 88 2024-09-04 09:46:07 fe80::6249:2830:b534:a3f8%12 POST /Git_IIS/repo-remoto/git-upload-pack - 80 GitUser1 fe80::6249:2830:b534:a3f8%12 git/2.44.0.windows.1 - 200 0 0 69 2024-09-04 09:46:09 fe80::6249:2830:b534:a3f8%12 POST /Git_IIS/repo-remoto/git-upload-pack - 80 GitUser1 fe80::6249:2830:b534:a3f8%12 git/2.44.0.windows.1 - 200 0 0 1083
Gli ultimi due righi sono dei Post eseguiti dal Web server IIS verso il Client e testimoniano la conclusione attesa del CLONE.
Es agginta riferimento remoto
Si aggiunge localmente il riferimento ad un repository remoto (che è vuoto):
Nel caso sia necessaria una autenticazione, si indica lo user@... :
git remote add foobar http://GitUser1@SPXMIW3658/Git_IIS/repo-remoto
Es Remote 2 (no upstream)
Nel caso di pubblicazione verso remoto e non ci siano branch dopo aver ricevuto l'errore "fatal: The current branch master has no upstream branch":
git push --set-upstream foobar master
Si suppone si sia configurato il repository remoto "foobar"
Es Remote 3 Scaricare
Il comando da usare è fetch
, può esser necessario un ulteriore comando git pull
git fetch foobar git pull
Si suppone si sia configurato il repository remoto "foobar"
Conflitti
Es 1 contenuto file conteso
Supponendo un server XXX con bare repository e due PC client A e B, un file "Prova.txt" ha una modifica dal PC A ed un'altra che si sovrappone a quella del PC B. (Per ora non mostro la soluzione al problema che sarà da implementare manualmente)
Sul PC A:
Il progetto si chiama 'AutoMouseOver' ed file in conflitto Prova.txt
uno due tre -------------- quattro cinque
Sul PC B:
File Prova.txt
uno due tre -------------- XXXX
Branch
Creazione del brach per lo sviluppo:
$ git branch develop $ git push -u origin develop
Creare un feature branch:
git checkout develop git checkout -b feature/nuova_funzione
e
Si posson portare subito le modifiche a "feature/nuova_funzione", poi add . e commit.
Per consolidare tutto sul branch "develop", ci spostiamo su develop ed effettuiamo l’unione (merge) del ramo:
git checkout develop git merge feature/nuova_funzione
Problemi Soluzioni
Agg.to server remoto NON-Bare
Si effettua un git push
su server remoto NON bare e si riceve un errore:
remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: is denied, because it will make the index and work tree inconsistent remote: with what you pushed, and will require 'git reset --hard' to match the work tree to HEAD. remote: You can set the 'receive.denyCurrentBranch' configuration variable remote: to 'ignore' or 'warn' in the remote repository to allow pushing into remote: its current branch; however, this is not recommended unless you remote: arranged to update its work tree to match what you pushed in some remote: other way.
Una soluzione è lanciare il seguente comando sul server:
git config receive.denyCurrentBranch ignore ----oppure: git config receive.denyCurrentBranch warn
Il file di configurazione .\.git\config
potrebbe esser così (non-bare repository):
[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true ignorecase = true [receive] denyCurrentBranch = ignore
Sul server sono recepite le modifiche ma non si vedranno i nuovi files a meno da non resettare tutto che riporterà, come voluto, alla versione sul client remoto. Sul server eseguire:
git reset --hard
Dopo questo il push funzionerà.
Fonti:
- Da stackoverflow.com
- How to convert a normal Git repository to a bare one? stackoverflow.com
Soluzione migliore e più semplice
La seguente evita ogni volta di andare sul server ed eseguire l'hard reset, quindi sul server una volta per tutte digitare:
git config receive.denyCurrentBranch updateInstead
questo creerà sul file "config":
[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true ignorecase = true [receive] denyCurrentBranch = updateInstead
Dai client ogni successivo push
sovrascriverà completamente quanto era in precedenza sul server con quanto è ora sul client.
Traformare un repository da non-bare a bare
In short: replace the contents of repo with the contents of repo/.git, then tell the repository that it is now a bare repository.
To do this, execute the following commands:
cd repo mv .git ../repo.git # renaming just for clarity cd .. rm -fr repo cd repo.git git config --bool core.bare true
Note that this is different from doing a git clone --bare /path/to/repo to a new location (as described qui).
Consider this scenario Your origin had 100 branches You have only checked out 10 of them locally Your bare repo will only have the 10 You send the bare repo somewhere It would be missing 90 repos If that's your intention, that's fine. If you needed a mirror of the remote/origin, this is not the way.
Mappa e Link
C# | Source Control | Git | Git in Visual Studio
DevOps Server - TFS | Visual Studio | MS SQL | Dizionario
Parole chiave: