Sneak Git

Alejandro el informático(@ainformatico), http://alejandroelinformatico.com/slideshows/

http://alejandroelinformatico.com/slideshows/ca/sneak-git/

Alejandro el informático(@ainformatico). 2011.

Licencia Creative Commons by-nc-sa.

Què és Git?

"Git is a free & open source, distributed version control system."

http://git-scm.com/

Distributed version control

"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."

http://en.wikipedia.org/wiki/Distributed_revision_control

Disclaimer

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 vs Mercurial vs SVN

git ens proporciona molts avantatges respecte a altres controls de versions com hg (mercurial) o svn (Subversion).

git vs hg

git

hg

git vs svn

git

svn

Llavors, per què Git?

Múltiples usos

Git bàsic

Com fer-ho?

Hi ha dues maneres de configurar git:

Els dos mètodes ens permeten tenir configuracions locals i generals.

Configuració

Alias
Poder usar alias en les comandes de git, per exemple: $ git fix com a alias de $ git checkout -b fix
Colors
Definir els colors per als logs i els diff
Arxius ignorats
Ignorar fitxers a nivell personal/usuari

Configuració II

Core
Espais, tabulacions, terminacions de línia
Merge
Definir l'eina per a usar

~/.gitconfig i /path/to/repo/.git/config

        
          [user]
            name  = John Doe
            email = john@doe.com
          [alias]
            fix = git checkout -b fix
          [diff]
            tool = vimdiff
          [color "diff"]
            old = red
            new = blue
        
      

Configuració per CLI

        
          $ git config [--global] user.name "John Doe"
          $ git config [--global] user.email "john@doe.com"
          $ git config [--global] alias.fix checkout -b fix
          $ git config [--global] color.diff auto
          $ git config [--global] core.editor vim
        
      

Crear repositori

Hi ha dues maneres depenent de si volem tenir un repositori compartit o personal.

Personal
$ git init {name}
Compartit
$ 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.

Primer commit

  1. Realitzar canvis en el repositori
    • $ git status
  2. Afegir els canvis
    • $ git add {file} [-a]
  3. Commit
    • $ 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
        #
        
      

Històric

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 <john@doe.com>
          Date:   Sat Oct 15 18:00:00 2011 +0200

          ADD main.c for our first commit
        
      

Branches

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}

Crear una branca
$ git branch {name}
Eliminar una branca de manera segura, si ja hem obtingut els canvis
$ git branch -d {name}
Eliminar una branca definitivament
$ git branch -D {name}

$ git checkout

Ens permet canviar de branca o restaurar el nostre Working directory o fitxer.

Crear una branca i canviar automàticament
$ git checkout -b {name}
Canviar a una branca
$ git checkout {name}
Restaurar el Working directory o fitxer.
$ 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

Tornar enrere

Per tornar enrere en els canvis que hem realitzat ho podem fer de diferents maneres:

Esborrar l'històric

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]

Crear una branca temporal

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}

Revertir canvis

Els canvis fets en commits anteriors es poden revertir i crear un nou commit amb l'estat d'aquell commit.

$ git revert {hash}

Workflows més usuals

Els workflows més usuals de fer servir en git utilitzen les branques per tal de poder separar el desenvolupament en diferents peces.

http://nvie.com/posts/a-successful-git-branching-model/

Workflows més usuals II

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.

Git avançat

stash

Guarda l'estat del repositori modificat en una pila de canvis que es poden aplicar en qualsevol moment.

$ 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.

Tag identificable
$ git tag v0.1 b547e84
Tag amb comentaris
$ git tag -a v0.1 -m "The first stable version" b547e84
Tag signat amb PGP
$ 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 <john@doe.com>
          Date:   Sat Oct 15 18:00:00 2011 +0200

          The first stable version
          
          commit b547e84694eadd45967c3504c12bb19bd19ce783
          Author: John Doe <john@doe.com>
          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.

  1. $ git bundle create {name} [--all|{tag}|{branch}|{git_date_format}]
  2. $ 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.

  1. $ git format-patch [{tag}|{hash}] [--stdout > file]
  2. $ git apply --stat {name}

        From 577869252ebd0c3c053715fe702e061b8441a6a3 Mon Sep 17 00:00:00 2001
        From: John Doe <john@doe.com>
        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 <john@doe.com>
            + *
            + * @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:

  1. $ git submodule init
  2. $ git submodule update

Hooks

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:

  1. Hooks de cara el client
  2. Hooks de cara el servidor

Hooks de cara el client

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.

Hooks de cara el client II

applypatch-msg
Verificar les directrius dels missatges
pre-applypatch
S'executa abans d'aplicar un patch
post-applypatch
S'executa després d'aplicar el patch

Hooks de cara el client III

Hooks de cara el servidor

S'executen en el servidor abans i després de fer push.

pre-receive
S'executa abans de fer push. Normalment per controlar permisos
post-receive
S'executa un cop acabat el procés de push. Notificacions, parsejar el missatge de commit i tancar tickets...
update
Igual que pre-receive però controla les branques per separat

Treballant en remot

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:

Treballant en remot - http[s]

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}]

Avantatges

Inconvenients

Treballant en remot - git protocol

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}]

Avantatges

Inconvenients

Treballant en remot - ssh

Podem fer pull o push mitjançant el protocol ssh.

git [pull|push] ssh://{[usuari@]servidor/path/to/repo} [{branca}]

Avantatges

Inconvenients

Treballant en remot - git remote

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}

Gitweb

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]

http://git.kernel.org

Gitosis / Gitolite

Són un conjunt d'scripts que ens permeten tenir un control exhaustiu dels usuaris i els seus permisos per a cada repositori.

Gitosis
https://github.com/res0nat0r/gitosis
Gitolite
https://github.com/sitaramc/gitolite

Github

És un hosting de repositoris git gratuït centrat principalment amb el desenvolupament Open Source, però amb característiques Premium.

https://github.com/

Bitbucket

Hosting de repostoris mercurial però des del 3 d'octubre de 2011 proporciona suport per a git.

https://bitbucket.org/

El següent pas

Links

Alejandro el informático(@ainformatico), http://alejandroelinformatico.com/slideshows/