Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

CSharp:Source Control - Git operazioni tipiche

From Aino Wiki

Jump to: navigation, search

Schema di scenario tipico

Git schema flusso main 01.png

Doc:

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 o index, 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 e fetch.

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
Git brach develop.png

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 nascosti gitk --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 init #Comando da dare nella cartella radice del progetto da conservare
  • git init ProgettoTest01.git
  • git init --bare repo-remoto #Crea un repository senza Working Directory
  • git init --shared=all ProgettoTest01.git #Crea un repository condiviso con tutti gli utenti
git add Ufficializza l'aggiunta dei nuovi files nell'indice dei files da gestire, i files sono aggiunti alla staging area
  • git add .
  • git add NomeFile.Estensione
  • git add -p #Avvia una sessione interattiva che permette di scegliere quali porzioni dei file modificati vanno aggiunte 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 log
  • git log *.cs
  • git log --oneline #visualizza i commit una riga per volta con in testa il codice identificativo del commit
  • git log --graph --all --oneline #visualizzerà tutti i commit anche quelli storici nascosti
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 stash
  • git stash listgit stash drop stash@{1} #Rimuove uno specifico stash (1)
  • git stash clear elimina tutti gli stash
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.
  • git push origin #
  • git push foobar master #Suposto che il repository remoto abbia alias "foobar"
  • git push --set-upstream foobar master #Suposto che il repository remoto abbia alias "foobar"
  • git push -u origin --all #fa il push di tutti i branches inclusi anche quelli che già sono in remmoto assicura che tutto sia propagato

NOTA Per capire cosa scrivere dopo "push" aprire il file config andare alla sezione [remote "XXX"], al posto di XXX ci può essere origin o foobar (che è un nome custom)

git fetch Per prelevare da Git (locale o remoto) sovrascrivendo i file locali, quindi ignorando tutte le modifiche locali
  • git fetch
  • git checkout origin/main

oppure

  • git reset --hard origin
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 remote -v          Per avere la URL del progetto corrente
  • git remote add foobar http://SPXMIW3658/Git_IIS/repo-remoto #Per aggiungere al repository locale il riferimento ad uno remoto
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 --all

NOTA 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 "HEAD" che punta sempre al commit su sui ci si trova

  • git branch bob 56674fb # qui sto usando la chiave del commit per assegnare una etichetta
  • git branch -d Br_Secondo # per cancellare l'etichetta (NON il commit!)
  • git branch #Per vedere l’elenco dei branch locali disponibili
  • git branch -r #Per vedere l’elenco dei branch remoti
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 fetch senza argomenti per aggiornare quel che è localmente deve corrispondere ai remote-tracking branches e git pull senza argomenti per fare il merge con quanto è in locale.

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
  • git pull
  • git pull foobar master

NOTA per capire cosa scrivere dopo "pull" aprire il file config andare alla sezione [remote "XXX"], al posto di XXX ci può essere origin o foobar (che è un nome custom)

git config Per impostare informazioni di configurazione locali o globali di Git.

NOTA per poter committare qualcosa occorre impostare l'utente corrente!

  • git config --list #Per avere l'elenco di tutti parametri di configurazione nel file config, es per le info sull'utente corrente
  • git config --global user.name "Giuseppe Aino" #Per impostare l'utente globale
  • git config --global user.email xxx.yyy@gmail.it #Per impostare l'email dell'utente globale

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:

Git branch 01.png

Si crea il seguente Branch chiamandolo "Br_Secondo"

git branch Br_Secondo 9c82359
Git branch 02.png

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:

Git bare repository 04.png

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:

Git bare repository push master 04.png

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:

Git bare repository clone 05.png

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):

Git fetch da remoto 01.png

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
Git conflict 01 PC A .png

Sul PC B:
File Prova.txt

uno
due
tre
--------------
XXXX
Git conflict 02 PC B.png

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
GIT 02.png

e

GIT 03.png

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
GIT 04.png

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:

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:

Author