http://alejandroelinformatico.com/slideshows/ca/sneak-git/
Alejandro el informático(@ainformatico). 2011.
Licencia Creative Commons by-nc-sa.
"distributed version control or decentralized version control (DVCS) keeps track of software revisions and allows many developers to work on a given project without necessarily being connected to a common network."
Totes les comparacions i comentaris que venen a continuació, són purament de l'autor d'aquest document i estan basades en la seva experiència treballant amb les eines documentades. No es pretén intentar canviar la mentalitat ni la percepció de cap persona ni molt menys desprestigiar alguna d'aquestes eines.
"No importa l'eina que facis servir, importa que en facis servir una i aquesta s'adapti a les teves necessitats." - Alejandro el informático
git
ens proporciona molts avantatges respecte a altres controls de versions com hg
(mercurial) o svn
(Subversion).
stash
merge
git
vs hg
git
hg
git
vs svn
git
:)
svn
branch
és en realitat un clon
Hi ha dues maneres de configurar git
:
Els dos mètodes ens permeten tenir configuracions locals i generals.
git
, per exemple: $ git fix
com a alias de $ git checkout -b fix
[user]
name = John Doe
email = [email protected]
[alias]
fix = git checkout -b fix
[diff]
tool = vimdiff
[color "diff"]
old = red
new = blue
$ git config [--global] user.name "John Doe"
$ git config [--global] user.email "[email protected]"
$ git config [--global] alias.fix checkout -b fix
$ git config [--global] color.diff auto
$ git config [--global] core.editor vim
Hi ha dues maneres depenent de si volem tenir un repositori compartit o personal.
$ git init {name}
$ git init --bare {name}
bare
or not to bare
El bare
indica si es tracta d'un repositori el qual permetrà que es facin commits d'altres persones. D'aquesta manera diferents persones poden fer push
/pull
sense trencar el working directory d'altres desenvolupadors.
$ git status
$ git add {file} [-a]
$ git commit [-m "ADD {file}"]
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# main.c
nothing added to commit but untracked files present (use "git add" to track)
$ git add main.c
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached >file>..." to unstage)
#
# new file: main.c
#
$ git commit [-m]
ADD main.c for our first commit
# Please enter the commit message for your changes.
# Lines starting with '#' will be ignored,
# and an empty message aborts the commit.
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached >file>..." to unstage)
#
# new file: main.c
#
Podem veure l'històric del nostre repositori per tal de veure quins canvis s'han realitzat i qui ha estat l'autor.
$ git log
commit 1a3024df85560d6b615a7a395c42a99180ed54cb
Author: John Doe <[email protected]>
Date: Sat Oct 15 18:00:00 2011 +0200
ADD main.c for our first commit
Les branques (branches) ens permeten fer un snapshot del repositori per a poder treballar sense tocar el desenvolupament principal, la branca master que és la branca per defecte que es crea.
Per tan podríem dir que tot en git
són branques.
$ git branch [-d|-D] {name}
$ git branch {name}
$ git branch -d {name}
$ git branch -D {name}
$ git checkout
Ens permet canviar de branca o restaurar el nostre Working directory o fitxer.
$ git checkout -b {name}
$ git checkout {name}
$ git checkout -f [filename]
merge
"Merging (also called integration) in revision control, is a fundamental operation that reconciles multiple changes made to a revision-controlled collection of files."
En la majoria de casos únicament hem d'executar:
$ git mergetool
Per tornar enrere en els canvis que hem realitzat ho podem fer de diferents maneres:
Podem esborrar l'històric fins a {n}
commits anteriors, perdent tot el que teníem fins ara i deixant el repositori en aquell estat.
$ git reset HEAD^{n} [--soft|--hard]
Podem crear una branca temporal per tal de poder veure com estava el repositori en un commit determinat i fer les accions pertinents.
$ git checkout {hash}
Els canvis fets en commits anteriors es poden revertir i crear un nou commit amb l'estat d'aquell commit.
$ git revert {hash}
Els workflows més usuals de fer servir en git
utilitzen les branques per tal de poder separar el desenvolupament en diferents peces.
Els workflows s'apliquen tan a desenvolupaments locals com remots.
Quan es desenvolupa una nova funcionalitat, es realitza un fix o un test, es demanen els canvis de la branca master i si cal es fa un merge, es proven els canvis i es pugen a la branca principal.
Normalment s'acostuma a tenir una persona encarregada de fer els merge
a master i controlar el flux de commits dels desenvolupadors.
stash
tag
bundle
patch
submodule
stash
Guarda l'estat del repositori modificat en una pila de canvis que es poden aplicar en qualsevol moment.
$ git stash [save {desc}]
$ git stash list
$ git stash show [-p] stash@{n}
$ git stash branch {name} [stash@{n}]
$ git stash apply [stash@{n}]
$ git stash pop [stash@{n}]
$ git stash drop stash@{n}
$ git stash clear
$ git stash [save {desc}]
Guardem l'estat actual del repositori modificat.
$ git stash save add main declaration
Saved working directory and index state On develop: add main declaration
HEAD is now at 1a3024d ADD main.c four our first commit
$ git stash list
Llistem l'estat de la pila de canvis.
$ git stash list
stash@{0}: On develop: add main declaration
stash@{1}: On fix: fixing bug #16338
stash@{2}: On test: hold for sockets test
$ git stash show [-p] stash@{n}
Llistem els canvis fets en l'estat n
de la pila.
$ git stash show -p stash@{0}
diff --git a/main.c b/main.c
index e69de29..9d9f7be 100644
--- a/main.c
+++ b/main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(void)
+{
+ printf("\nHello World.\n");
+ return 0;
+}
$ git stash show stash@{0}
main.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
$ git stash branch {name} [stash@{n}]
Traslladem els canvis de l'estat n
a la branca {name}
i esborrem l'estat de la pila.
$ git stash branch test stash@{0}
Switched to a new branch 'test'
# On branch test
# Changed but not updated:
# (use "git add >file>..." to update what will be committed)
# (use "git checkout -- >file>..." to discard changes in working directory)
#
# modified: main.c
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (4a1fb8c41198a8966a77b506b454745fbaa2587e)
$ git stash apply [stash@{n}]
Apliquem els canvis de l'estat n
.
$ git stash apply
# On branch develop
# Changed but not updated:
# (use "git add >file>..." to update what will be committed)
# (use "git checkout -- >file>..." to discard changes in working directory)
#
# modified: main.c
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash pop [stash@{n}]
Igual que $ git stash apply [stash@{n}]
però elimina l'estat de la pila
$ git stash pop stash@{0}
# On branch develop
# Changed but not updated:
# (use "git add >file>..." to update what will be committed)
# (use "git checkout -- >file>..." to discard changes in working directory)
#
# modified: main.c
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (4a1fb8c41198a8966a77b506b454745fbaa2587e)
$ git stash drop stash@{n}
Elimina l'estat n
de la pila.
$ git stash drop stash@{0}
Dropped stash@{0} (4a1fb8c41198a8966a77b506b454745fbaa2587e)
$ git stash clear
Elimina tota la pila.
$ git stash clear
tag
Els tags o etiquetes ens permeten marcar i identificar un punt en concret de tot l'històric del nostre repositori.
Normalment es fan servir per identificar releases.
$ git tag v0.1 b547e84
$ git tag -a v0.1 -m "The first stable version" b547e84
$ git tag -s v0.1 -m "The first stable version" b547e84
$ git tag [-l {pattern}]
$ git tag -l v0.*
v0.1
v0.2
$ git show v0.1
tag v0.1
Tagger: John Doe <[email protected]>
Date: Sat Oct 15 18:00:00 2011 +0200
The first stable version
commit b547e84694eadd45967c3504c12bb19bd19ce783
Author: John Doe <[email protected]>
Date: Sat Oct 15 18:00:00 2011 +0200
ADD basic main declaration to main file
diff --git a/main.c b/main.c
index e69de29..9d9f7be 100644
--- a/main.c
+++ b/main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(void)
+{
+ printf("\nHello World.\n");
+ return 0;
+}
bundle
Un bundle
és un paquet que conté tot o part del nostre repositori, i és fàcil de transportar i clonar.
$ git bundle create {name} [--all|{tag}|{branch}|{git_date_format}]
$ git pull|clone {name} [{branch}]
patch
Un patch
és un fitxer que conté els canvis d'un o més commits per tal d'aplicar-los en un altre repositori.
$ git format-patch [{tag}|{hash}] [--stdout > file]
$ git apply --stat {name}
From 577869252ebd0c3c053715fe702e061b8441a6a3 Mon Sep 17 00:00:00 2001
From: John Doe <[email protected]>
Date: Sat, 15 Oct 2011 18:00:00 +0200
Subject: [PATCH] ADD main declaration documentation
---
main.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/main.c b/main.c
index 9d9f7be..6af0170 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,13 @@
#include <stdio.h>
+/**
+ * The main declaration
+ *
+ * @author John Doe <[email protected]>
+ *
+ * @return int
+ *
+ * */
int main(void)
{
printf("\nHello World.\n");
}
submodule
Ens permet tenir un repositori git
dintre d'un altre repositori, per exemple un projecte principal per el qual es desenvolupen plugins.
Una nota important sobre submodule
és que aquests no es mantenen sincronitzats automàticament, ho hem de fer manualment i per a cada canvi que es faci en el submodule
hem de fer un commit en el nostre repositori principal.
submodule
II
Afegir un submodule
.
$ git submodule add ssh://server/path/to/repo {destination}
Initialized empty Git repository in /path/to/repo/{destination}
[...]
$ git st
# On branch develop
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: .gitmodules
# new file: {destination}
#
submodule
III
Quan fem un clon d'un repositori que té associat un o més submodule
, aquests no estaran inicialitzats per tan haurem de:
$ git submodule init
$ git submodule update
Els hooks són scripts que s'executen quan hi ha un determinat esdeveniment. Aquests scripts es troben en el directori .git/hooks
del nostre repositori.
Podem agrupar els hooks en:
Són únicament del client, per tan cap altre persona els pot modificar i per tan no es tranfereixen en un clon, push
o pull
.
pre-commit
prepare-commit-msg
commit-msg
post-commit
applypatch-msg
pre-applypatch
patch
post-applypatch
patch
pre-rebase
rebase
. Evitar rebase
en commits que han estat pujatspost-checkout
checkout
. Per inicialitzar el working directory, compilar, documentació...post-merge
merge
correctament. Canviar permissos, copiar fitxers...
S'executen en el servidor abans i després de fer push
.
pre-receive
push
. Normalment per controlar permisospost-receive
push
. Notificacions, parsejar el missatge de commit i tancar tickets...update
pre-receive
però controla les branques per separat
Quan treballem en remot fem push
a un repositori de tipus bare
quan ja tenin una possible versió final dels nostres canvis. Normalment en local es treballa en branques i un cop acabada la feina fem merge
amb la nostre branca master per tal de fer push
d'aquesta cap a una branca de test o implementació que serà revisada i després combinada amb la branca master remota.
Tenim diferents maneres d'enviar els nostres canvis:
ssh
patch
Pensat per repositoris de només lectura, i en determinats casos en repositoris d'escriptura.
git [pull|push] http[s]://servidor/path/to/repo} [{branca}]
Idealment el git protocol està pensat per tenir respositoris read-only, ja que no hi ha control d'usuaris i permisos.
git [pull|push] git://{servidor}/path/to/repo.git [{branch}]
git
ssh
Podem fer pull
o push
mitjançant el protocol ssh
.
git [pull|push] ssh://{[usuari@]servidor/path/to/repo} [{branca}]
ssh
ssh
al servidor
Podem guardar alias per als servidors que fem servir, per tal de facilitar la nostre gestió.
$ git remote add {name} ssh://server/path/to/repo
A partir d'aquest moment podem fer:
$ git push {name} {branch}
git
ens permet crear un visualitzador web del nostre repositori, normalment per accés local o de xarxa local però també pot servir d'accés públic si es configura junt amb el nostre servidor web.
Ens permet veure els commits, diff
, log
, branch
, tag
... en el nostre navegador web.
$ git instaweb [--httpd=lighttpd|apache2|webrick] [--stop]
Són un conjunt d'scripts que ens permeten tenir un control exhaustiu dels usuaris i els seus permisos per a cada repositori.
ssh
branch
, tag
i repositori
És un hosting de repositoris git
gratuït centrat principalment amb el desenvolupament Open Source, però amb característiques Premium.
Hosting de repostoris mercurial però des del 3 d'octubre de 2011 proporciona suport per a git
.
hg
a git
, http://bit.ly/33872nsvn
a git
, http://bit.ly/qa7c0B$ git init new-project