IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

http://anonymous@svn.projectes.lafarga.cat/svn/iceupc/LinuxProgramacio/moodle/sessio2/transparencies/ControlDeVersions.pdf

Contingut

Sistemes distribuits. GIT vs SVN o CVS

TODO http://files.zend.com/help/Zend-Studio/content/git_and_github.htm

Introducció

Conceptes

Git és un distributed version control system. Entorn els VCS hi ha una sèrie de conceptes que és important conèixer o al menys anar introduït de forma gradual per tal de poder treballar amb aquest tipus d'eïnes.

  • Version control system: és el nom genèric utilitzat per fer referència a totes les aplicacions que permeten portar un control de les versions dels fitxers d'un projecte informàtic. Exemple de VCS són git,CSV,Subversion
  • Distributed version control system: els CVS es poden classificar en distribuïts o centralitzats. El sistemes centralitzats tenen una arquitectura "Client Servidor" o un repositori fa les tasques de repositori central o servidor i múltiples clients treballen en aquest repositori/servidor central. En el cas dels sistemes distribuïts l'arquitectura és P2P, és a dir descentralitzada on múltiples repositoris distribuïts en múltiples màquines treballen de forma conjunta sense haver una relació jeràrquica ni cap repositori/servidor que sigui central o principal. Els VCS distribuïts són posteriors als centralitzats i per aquesta raó sovint al repositoris no distribuïts simplement no se'ls hi aplica cap classificació concreta i simplement se'ls anomena VCS.
  • Repository: Un repositori conté tota la història, les diferents versions a través del temps dels fitxers així com les diferents branques i etiquetes (branches and tags). Cal tenir en compte que a git cada copia d'un repositori és una còpia completa. No podem veure un repositori com un "simple directori" ja que de fet és una estructura de dades més complexa, en certa manera és més adequat veure un repositori com una mena de base de dades que conté fitxers i metadades, és a dir tota la informació extra necessària per emmagatzemar l'història de revisions, comentaris dels commits, etiquetes, branques, etc. Nota: de fet com tot en Linux, al final un repositori si és un conjunt de fitxers emmagatzemats a un directori, més concretament si estem treballant en una carpeta concreta podem saber si és un repositori git si té una carpeta oculta anomenada .git. Vegeu git ls-files
  • Working directory: aka àrea de treball. Físicament es tracta d'una carpeta i el seu subconjunt de fitxers i subcarpetes a on el desenvolupador està creant/modificant/eliminant fitxers per a un projecte informàtic. Vegeu git ls-files.
  • Working tree: The working tree contains the content of a commit which you can checkout from the Git repository. You can modify the content and commit the changes again to the Git repository. The user works on a collection of files which may originate from a certain point in time of the repository. The user may also create new files or change and delete existing ones. The current collection of files is called the working tree.

A standard Git repository contains the working tree (single checkout of one version of the project) and the full history of the repository. You can work in this working tree by modifying content and committing the changes to the Git repository. . [1]

  • Commit: Els desenvolupadors fan commits dels seus canvis a la còpia de treball cap als repositoris. És tracta per tant d'una operació que permet reflectir els canvis en l'àrea de treball en el repositori. En anglès té múltiples significats, però una traducció "adequada" en l'àmbit de git és depositar/entregar/cometré. Un commit genera una nova revisió del contingut del repositori. En certa manera és l'operació contraria a checkout (que aplica canvis del repositori cap a l'àrea de treball). Les revisions es poden recuperar més endavant per exemple si es vol veure el codi font d'un fitxer d'una versió anterior a l'actual. Cada commit és una estructura de dades, de fet es parla del concepte commit object, és a dir una estructura de dades que conté tant la revisió en si com metadades: autor, missatge de descripció associat a un commit, dat, identificador únic (un hash), etc. Vegeu git commit, git log
  • Revision: revisió en català. És la paraula utilitzada per fer referència a una versió concreta d'un fitxer, és a dir al contingut que tenia el fitxer en el moment x. Els VCS permeten recuperar versions antigues de fitxers o avançar cap a versions més noves de fitxers (versions que poden haver creat altres desenvolupadors, nosaltres mateixos en repositoris remots, etc). Cal tenir en compte que cada canvi que es fa automàticament a un fitxer no crear una revisió, sinó que només es guarden aquells canvis dels quals es realitza un commit al repositori. Les revisions es poden consultar amb git log
  • Checkout: l'operació checkout és realitzar sobre revisions d'un repositori, és a dir, és la operació que permet transformar/modificar la nostra àrea de treball en una revisió concreta del nostre repositori. Per defecte la revisió que s'escull si no s'indica res al contrari és la HEAD (la última revisió disponible, la més actual). Es pode obtenir/fer checkouts de qualsevol revisió (una revisió es crea al realitzar un commit en un repositori), de branques o d'etiquetes. Vegeu també l'ordre git checkout
  • Staging: . Quan es parla d'staging amb git es fa referència a totes les tasques de preparació i organització d'un commit. La paraula anglesa Staging és tradueix al català com a 'posada en escena'/'preparació'/'muntatge' [2]. Fer un stage d'un fitxer amb git és simplement preparar-lo per a un commit. ës una diferència important respecte a altres CVS ja que git permet fer un commit parcial de només cert fitxers locals canviats des de l'últim commit. Per exemple si estem treballant en dos noves "features" de la nostra aplicació i una esta acabada però l'altre no, podem fer un commit de la preparada només. Vegeu les comandes git add/git rm i git reset.

GitStaging.png GitRemoteOperations.png GitAllOperations.png

  • Staging area: aka index. És l'àrea intermèdia entre l'àrea de treball i el repositori git. Tenin en compte que el repositori git no té perque ser el remot, recordant sempre que parlem d'un sistema distribuit on en local també tenim un repositori de treball al qual i fem commits. Vegeu git add/git status/git reset.
  • Branches: Un branca és un commit que té un nom concret (aka named pointer). Escollir un branca d'un repositori git com a working tree és el que en terminologia git s'anomena checkout a branch. Si es treballa en una branca els commits realitzats avancen el punter HEAD només en aquesta branca i no pas en la branca principal. Per cert la branca principal se sol anomenar master i és la branca per defecte o el que és el mateix un projecte sense branques només té la branca master. Vegeu git branch

IMPORTANT: COMPTE!: Oco als que veniu de treballar amb altres CVS com Subversion on el significat de checkout es molt diferent i es confon amb git pull

  • Tags: Un tag és una etiqueta. És un altre forma de posar un nom a un commit concreat per tal d'identificar-lo més fàcilment. Per exemple les etiquetes es poden utilitzar per identificar commits de versions del programa (v1.0, v0.1) o releases que poden tenir fins i tot un nom concret (release codename). Vegeu git tag
  • Branches vs tags: tots dos són commit named pointers, la diferència és que a les branques cada commit avança l'apuntador HEAD només en aquella branca (i les noves referències a la branca apunten a aquest nou pauntador) i en canvi els tags no avançant mai en el cas de commits (són estàtics). Vegeu detached HEAD
  • URL: S'utilitzen les URL per determinar la localització d'un repositori. Per exemple: https://github.com/acacha/ebre-inventory
  • HEAD: HEAD és un link simbòlic que sol apuntar a la branca que actualment s'ha checkejat (realitzat un checkout). Algunes vegades HEAD no apunta a la versió més actual sinó que si per exemple és fa un checkout d'un tag o d'un commit concret àntic aleshores estem a l'estat/mode detached HEAD mode. Si es fa un checkout d'un commit specific el HEAD apunta a aquest commit. En aquest estat un commit no actualitzarà ni mourà el Head pointer, l'única forma de fer-ho es creant una branca al fer el checkout (vegeu l'opció -b de git checkout. Es pot fer referència a versions anteriors a HEAD amb HEAD~1, HEAD~2... Si es va una operació switch branches el HEAD pointer es mou cap al últim commit de la branca especificada. Vegeu git checkout
  • switch branches: TODO

Recursos:

Estat dels fitxers

IMPORTANT: Per a cada operació normal amb fitxer (crear/afegir/add

  • Untracked files: Són fitxers presents a un directori de treball però que no han estat indexats, és a dir no estan a l'index o stagging area. Amb aquest fitxers hi ha dos opcions, o són errors i s'esborren/moun tal qual amb comandes tradicionals unix com rm o mv o s'afegeixen a git amb la comanda git add

Instal·lació

$ sudo apt-get install git

Fitxers instal·lats

Binaris:

$ dpkg -L git | grep bin
/usr/bin
/usr/bin/git
/usr/bin/git-upload-pack
/usr/bin/git-shell
/usr/bin/git-upload-archive
/usr/bin/git-receive-pack

Configuració:

$ dpkg -L git | grep /etc
/etc
/etc/bash_completion.d
/etc/bash_completion.d/git


Altres paquets

$ sudo apt-get install git   --> tabuleu dos cops
git                  git-annex            git-core             git-doc              git-flow             gitit                gitolite             gitstats             
gitalist-common      git-arch             git-cvs              git-dpm              gitg                 gitk                 gitpkg               git-stuff            
gitalist-fastcgi     git-buildpackage     git-daemon-run       git-el               git-gui              gitmagic             git-review           git-svn              
git-all              git-cola             git-daemon-sysvinit  git-email            github-cli           git-man              git-sh               gitweb

Configuració

Repositoris

La configuració és troba a la carpeta oculta:

.git

que es pot torbar a cada arrel del repositori. Per exemple:

$ cat  /usr/share/webfaltes/.git/config
[core]
	repositoryformatversion = 0
	filemode = true
	logallrefupdates = true
[remote "original"]
	url = https://github.com/acacha/webfaltes.git
	fetch = +refs/heads/*:refs/remotes/original/*
	pushurl = https://github.com/acacha/webfaltes.git
	push = HEAD:refs/for/refs/heads/master
[branch "master"]
	remote = original
	merge = refs/heads/master
[gerrit]
	createchangeid = true

per user basis ~/.gitconfig

Un exemple:

$ cat /home/sergi/.gitconfig 
[user] 
	name = Sergi Tur Badenas
	email = sergitur@email.com

A Eclipse, amb el plugin Egit es pot configurar aquest fitxer a:

Preferences > Team > Git > Configuration > User Settings

per system basis

.gitconfig

TODO: Eclipse also supports the .gitconfig for excluding certain files from the Git repository.

.gitignore

.gitignore gitignore

NOTA: gitignore només serveix per a fitxers untracked. Cal utilitzar rm --cached per a fitxers que ja han estat pujats al repositori

Workflow

http://www.google.es/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&docid=aycoS6sby-IilM&tbnid=aaJyCCLrnLKk8M:&ved=0CAUQjRw&url=http%3A%2F%2Fwww.markus-gattol.name%2Fws%2Fscm.html&ei=1R5bUd_9Dcm2Pe-IgNAB&bvm=bv.44697112,d.ZWU&psig=AFQjCNHYCMNZdD9rlwBSFthZy9vuqdy1Ig&ust=1365012495872948

Git workflow and cheat sheet.png
  • git_workflow_and_cheat_sheet.png

Exemples de workflows

Arquitectura: servidors de desenvolupament, producció i servidors locals dels desenvolupadors

Imatges:

git-repo-desired.png

Ús

CLI. Comanda git

Preparant un repositori

Aquestes comandes se solen utilitzar només inicialment al configurar/preparar un repositori i més endavant no formen part del workflow del dia.

git init

Permet convertir/inicialitzar una carpeta amb codi ja existent però que no té res a veure amb git amb un directori de treball git

Si feu un git status en una carpeta que no sigui un directori de treball git:

$ git status
fatal: Not a git repository (or any of the parent directories): .git

Ara inicialitzem:

$ git init
Initialized empty Git repository in /var/www/app_name/.git/

Com podeu veure crea la carpeta ./git. Ara si fem un git status:

$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	application/
#	assets/
#	index.php
#	license_codeigniter.txt
#	license_myclientbase.txt
#	robots.txt
#	system/
#	uploads/
nothing added to commit but untracked files present (use "git add" to track)

Esta tot pendent d'afegir. El procediment normal per fer un import dels fitxers locals és:

$ git add .
$ git commit -m "Initial commit"
$ git remote add origin https://github.com/acacha/ebre-invoice 

NOTA: Canvieu la URL per la URL d'un repositori git, per exemple un de github

Comproveu el nou repositori:

$ git remote -v
origin	https://github.com/acacha/ebre-invoice (fetch)
origin	https://github.com/acacha/ebre-invoice (push)

Ara fem un pull al repositori remot per obtenir la última versió i un push per pujar el que s'ha fet commit en local:

$ sudo git pull origin master
$ sudo git push origin master

Recursos:

git clone

La comanda git clone obté una còpia d'un repositori git ja existent (local o remot). A més també genera el famós "remote" per defecte: origin.

La sintaxi és.

$ git clone <repo> <directory>

Si no s'especifica el directory el nom del directori creat en local coincidirà amb el nom del projecte. Com la comanda git init és tracta d'una operació que se sol fer un sol cop.

Cal recordar que el repo el podem indicar com una URL amb el protocol http o https però que també es possible utilitzar SSH o patch locals. Per exemple:

$ git clone git@github.com:acacha/adminlte-laravel.git

Crearà una carpeta adminlte-laravel que serà un clon del repositori git de github que podeu veure a la URL:

https://github.com/acacha/adminlte-laravel

és a dir que és equivalent a:

$ git clone https://github.com/acacha/adminlte-laravel

Però l'accés el fem per SSH.

IMPORTANT: Per poder accedir per SSH a Github prèviament cal configurar les claus SSH. Vegeu: https://help.github.com/articles/generating-ssh-keys/

De fet és important tenir en compte que podem utilitzar l'accés SSH amb qualsevol màquina remota a la que tinguem accés SSH, per exemple:

$ git clone sergi@acacha.org:/home/sergi/path_to_git_repo

És a dir volem obtenir una còpia del repositori remot que podem trobar a la carpeta /home/sergi/path_to_git_repo del servidor acacha.org al qual accedim amb l'usuari sergi. De fet també podeu obtenir una copia d'un repositori local amb:

$ git clone PATH_RELATIU_O_ABSOLUT_TO_GIT_REPO

Per exemple

$ git clone repo1 repo2

Crearà la carpeta repo2 amb una còpia del repositori que es troba a la carpeta repo1 i fixeu-vos que crearà igualment el remote origin:

$ cd repo2
$ git remote -v
origin	/home/sergi/esborrar/repo1 (fetch)
origin	/home/sergi/esborrar/repo1 (push)

Com podem fer un clone sobre una carpeta ja existent que és idèntic o amb contingut molt similar al repositori? Un truc senzill és:

$ cd carpeta_ja_existent
$ git clone https://PAT_TO_myrepo.com/git.git temp
$ mv temp/.git .
$ rm -rf temp
$ git status

Si el contingut local és idèntic al repositori remot la comanda status ens indicarà que tot està al dia. Si tenim petits canvis ens mostrarà quins són. Com podeu veure el que hem fet realment és obtenir una copia de la carpeta .git del repositori remot i la hem copiat a la carpeta local.

Resources

git clone i branques remotes

Cal tenir en compte que només la branca remota master s'obté al fer un clone:

$ git clone https://github.com/acacha/adminlte-laravel
$ cd adminlte-laravel
$ git branch
* master

Però podeu veure totes les branques amb:

$ git branch -a

Les branques remotes tenen com a nom:

remotes/nom_remote/NOM_BRANCA

per exemple:

remotes/origin/HEAD
remotes/origin/master
remotes/origin/development
etc...

Podeu obtenir qualsevol branca amb git checkout per exemple

$ git checkout remotes/origin/development

Però això si només voleu veure la branca. Si hi voleu treballar millor que feu:

$ git checkout -b remotes/origin/development

I ara estareu a la branca development

$ git branch
* development
master


Recursos

git config

Per configurar el nom d'usuari i el email:

# configure the user which will be used by git
# Of course you should use your name
git config --global user.name "Example Surname"

# Same for the email address
git config --global user.email "your.email@gmail.com" 

Vegeu també ~/.gitconfig

Comandes de treball

git status

Segurament una de les comandes més importants i interessants. Mostra l'estat (especialment les diferències si n'hi ha) de la nostra àrea de treball comparant-la sempla amb l'index (stagging area) i el repositori.

Si tenim un directori de treball net (és a dir sense canvis) el missatges que mostrarà status és:

$ git status
# Not currently on any branch.
nothing to commit (working directory clean)

A mesura que fem canvis la sortida de git status anirà canviant. Per exemple si afegim un fitxer (o el mateix s'aplica a un directori amb o sense subfitxers o subdirectoris):

$ touch a
$ git status
# Not currently on any branch.
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	a
nothing added to commit but untracked files present (use "git add" to track)


Com podeu veure ens indica que tenim un fitxer nou en el directori de treball del qual no s'està fent un seguiment per part de git (untracked file). S'ha d'afegir amb gitt add:

$ git add a

Ara l'estatus és:

$ git status
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   a

Com podeu veure tenim un fitxer a l'stagging area o index. Es pot desfer add amb git reset. Ara tenim doncs un canvi (que consisteix en un fitxer nou afegit al projecte) i si volem reflectir el canvi al repositori cal fer un commit:

$ git commit

I el directori de treball tornarà a estar net:

$ git status
# Not currently on any branch.
nothing to commit (working directory clean)

Si volem desfer el canvi (és a dir esborrar el fitxer):

$ rm a
$ git status
# Not currently on any branch.
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
# 
# 	deleted:    a
#
no changes added to commit (use "git add" and/or "git commit -a")

Ara tenim dos opcions:

1) Desfer el canvi:

$ git checkout -- a

En aquest cas restaurarà el fitxer esborrat

2) Esborrar realment el fitxer també a git

$ git rm a

I ara només cal fer el commit:

$ sudo git status
# Not currently on any branch.
# Changes to be committed:
#    (use "git reset HEAD <file>..." to unstage)
#
#	deleted:    a
#
$ git commit

El fitxer ja no està al HEAD del repositori

NOTA: tingueu en compte que a la història el fitxer continuarà existint, i això pot ser un problema en el cas d'errors, per exemple al pujar informació sensible com paraules de pas al repositori. Consulteu [[]]

Amb les modificacions el procediment és ídentic

$ edit a
$ git status
# Not currently on any branch.
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   a
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
$ git commit

Per més informació consulteu el manual:

$ man git status

Recursos

git add

IMPORTANT: Teniu en compte els 2 estats de git [3] i les diferències entre un commit i un add

Les opcions d'ús són:

$ git add <file>
$ git add <directory>
$ git add -p

Per afegir un fitxer concret:

$ git add nom_fitxer

Per afegir un directori:

$ git add nom_directori

Això afegeix el directori i tots els subfitxers i subdirectoris. Una opció útil per fer un add de tot els fitxers nous és:

$ git add .

Finalment es pot fer

$ git add -p

Vegeu també git status


Recursos:

git reset

És l'operació contraria a git add. Vegeu git status per veure un exemple.

Per exemple podeu tornar al últim commit (eliminant els canvis locals des de l'últim commit) amb:

$ git reset --hard
git rm

És similar a add en el sentit que també registra un canvi del directori de treball en el index o stagging area però concretament "afegeix" el registre de l'esborrament d'un fitxer. Vegeu git status per veure un exemple

git commit

TODO

git log

Sense opcions mostra l'historial de commits realitzats al repositori:

$ git log
commit bbc13336cd1c32fa1eeab7a63c86f11c9d7de144
Author: Sergi Tur Badenas <sergitur@ebretic.com>
Date:   Wed Sep 11 10:36:39 2013 +0200

   TODO

commit 42e426319c23e37b37fa9393e26011b163644af0
Author: root <root@pc02maninfo.(none)>
Date:   Tue Sep 10 14:07:36 2013 +0200

   First release

commit 07af0497dec002435b8ba40f8de95b22fd9b691e
Author: Sergi Tur Badenas <sergitur@ebretic.com>
Date:   Tue Sep 10 04:47:49 2013 -0700

   Initial commit

Com podeu veure cada commit té un hash que l'identifica (assegurant que és un identificador únic i al mateix temps la integritat del sistema), l'autor i el seu email i la data del commit.

Els commits s'identifiquen amb un hash SHA1 i es representen en hexadecimal.

Es poden utilitzar altres formats de sortida:

$ git log --pretty=oneline

On altres opcions són:

short, medium, full, fuller, email, raw and format:<string>

Per més informació es pot consultar el manual:

$ man git log

Recursos:

git reflog

TODO

git ls-files

Mostra informació dels fitxers que estan tant al directori de treball (working tree) com a l'index (staging area).

Sense opcions:

$ git ls-files

Que equival a:

$ git ls-files -c

és a dir mostra els fitxers en estat cached

amb:

$ git ls-files -v

Mostra una lletra al davant de cada fitxer:

H application/.htaccess

On segons el manual que es pot consultar amb:

$ man git ls-files
  • H: cached
  • S: skip-worktree
  • M: unmerged
  • R: removed/deleted
  • C: modified/changed
  • K: to be killed
  • K: other

Cal tenir en compte que qualsevol lletra anterior que aparegui en mínúscules és --assume-unchanged. Per tant, com es poden mostrar els fitxers que estan en mode --assume-unchanged?

$ git ls-files -v | grep ^[a-z]
h application/config/config.php
h application/config/inventory.php

NOTA: Els fitxers untracked, és a dir aquells que s'han creat nous però no s'ha fet una operació git add sobre els mateixos, no apareixen. cal utilitzar l'opció -o (others)

$ touch a
$ git ls-files -o -v
? a

es poden combinar opcions:

$ git ls-files -cdvmosk

Són fitxers que s'ha marcat ignorar els canvis amb:

$ git update-index --assume-unchanged application/config/config.php

Es poden desmarcar amb:

$ git update-index --no-assume-unchanged application/config/config.php

Recursos:

Branques

Una manera d'entendre les branques es entendre-les com una petició al repositori de que gestioni un nou historial en el nostre projecte independent de l'historial principal.

NOTA: Tingueu en compte doncs com afecta el tema de les branques a comandes com git log encarregades de mostrar l'història del repositori

La comanda checkout és l'utilitzada per seleccionar una branca o un altre, cal tenir en compte la "jerga" utilitzada com canviar de branca o seleccionar una branca (switch branch).

Finalment les branques es poden tornar unir ja sigui amb la branca principal o altres branques en el que es coneix com el concepte de merging i l'operació merge.

IMPORTANT: les branques de GIT no són com les de subversion! Amb git les branques són molt més utilitzades ja que s'entenen com una eina utilitzada en el workflow del dia dia del treball amb git


Un branca representa un línia independent de desenvolupament. Les branques són una abstracció per al procés de edit/stage/commit. Es pot pensar en les branques com una forma de demanar una nova i independent directori de treball, staging area i història del projecte. Els nous commits es guarden en la nova branca que de fet acaba sent un fork de la història del projecte principal.

Recursos:

Detached Head

L'estat Detached Head succeïx quan es realitzen un checkout sense crear una nova branca. Podem saber si estem en aquest estat si al fer:

$ git branch
* (no branch)
  master

Com podeu veure no tenim cap branca. Si es realitzen commits en aquest estat encara que es facin després push sembla que els canvis no es "pugen" al repositori.

Per no tenir el problema en comptes de fer:

$ git checkout my_new_branch

NOTA: Cal tenir en compte que l'ordre checkou ens avisa de que entrarem en aquest estat i ens recomana utilitzar l'opció -b

Cal fer:

$ git checkout -b my_new_branch

De fet arribats al punt de estar en aquest ·estat indesitjat" sempre estem a punt de fer:

$ git checkout -b my_new_branch

Per fer que el head detached actual passi a ser el head de una nova branca. I si volem aplicar els canvis de la branca nova a master només cal fer una operació merge:

TODO

Vegeu també git reflog

Recursos

git branch

Aquesta comanda permet llistar, canviar el nom i esborrar branques:

$ git branch
* master

La branca marcada amb un asterisc és la branca actual.

Mostra totes les branques del repositori

IMPORTANT: El canvi de branques no es fa amb esta comanda sinó amb les comandes git checkout i git merge.

Per crear una nova branca:

$ git branch <branch>

cal tenir en compte que això no seleccion aquesta branca. Vegeu git checkout.

Per esborrar una branca:

$ git branch -d <branch>

és una operació segura ja que git no permet esborrar la branca si i ha operacions de merge pendents (unmerged changes). Per forçar l'esborrament de la branca:

$ git branch -D <branch>

per canviar el nom d'una branca

$ git branch -m <branch>

canvia el nom de la branca a la que estem.

git checkout

La comanda git checkout permet navegar entre les branques i realitzar l'operació que normalment anomenem canviar de branca (branch switching). Les branques es creen prèviament amb git branch. Al fer un checkout d'una branca els fitxers del directori de treball s'actualitzen per coincidir amb els de la branca escollida i es configura git per tal de registrar tots els nous canvis en aquesta branca. Permet per tant seleccionar en quina línia de desenvolupament es vol treballar.

Per seleccionar una branca:

$ git checkout <existing-branch>

La branca ja ha d'existir. Si es vol fer el checkout al mateix temps que es crea la branca:

$ git checkout -b <new-branch>

TODO:

$ git checkout -b <new-branch> <existing-branch>

TODO:

In the previous module, we saw how git checkout can be used to view old commits. Checking out branches is similar in that the working directory is updated to match the selected branch/revision; however, new changes are saved in the project history—that is, it’s not a read-only operation.

Recursos:

git merge

L'operació merge (en anglès fusionar/unir) es la forma que té git de agafar 2 o més línies de desenvolupament (branques) i unir-les tot realitzant un control de canvis i resol·lució de possibles conflictes. L'operació més habitual és aplicar els canvis d'una branca a la branca principal però es poden fer operacion merge entre qualsevol nombre de branques.

Vegem algun exemple:

$ git merge <branch>

En aquest cas estem indicant a git que volem que la branca "<branch>" es fusioni amb la branca actual. Podeu obtenir la branca actual a la que esteu amb:

$ git branch

La marcada amb asterisk és l'actual. És important tenir en compte que la branca "<branch>" no es veu afectada i no té cap canvi i és la branca actual a la que se li apliquen els canvis.

Normalment l'operació doncs es primer seleccionar la branca sobre la que es vol realitzar l'operació:

$ git branch <branca>
$ git merge <unaltrebranca>
$ git branch -d <unaltrebranca>

L'última comanda es opcional però se solen esborrar les branques obsoletes.

TODO:

$ git merge --no-ff <branch>

Al realitzar un merge podem trobar diferents algoritmes o formes en que el sistema git realitza el merge.

Recursos:

git mergetool

Es poden utilitzar aplicacions gràfiques:

Vegeu Meld#Meld_i_Git
git tag

Per mostrar els tags:

$ git tag

No mostrarà res si no teniu cap tag.

Per crear un tag:

$ git tag -a v0.1

I apareixerà el vostre editor preferit per afegir un missatge relacionat amb el tag.

IMPORTANT: Cal tenir en compte que els tags en aquest moment només s'apliquen al repositori local. Per compartir-los cal fer un push:

$ git push origin v0.1

NOTA: Suposem que el repositori local es diu origin. Podeu veure els repositoris amb git remote -v

això és coneix com compartir els tags o Sharing Tags.

Si es tenen múltiples tags en local i es volen compartir tots:

$ git push origin --tags

També podem crear tags de versions anteriors a l'actual. Per exemple:

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

Per posar un tag a la versió en negreta:

$ git tag -a v1.2 -m 'version 1.2' 9fceb02

On 9fceb02 és l'identificador del commit (o part d'ell també serveix)


Recursos:

Exemples

Importar

Si teniu codi i el voleu important a un repositori acabat de crear, cal seguir els següents passos:

$ cd CARPETA_CODI_LOCAL
$ git init

Ara s'afegeixen localment els fitxers que interessin amb:

$ git add nom fitxer

Podeu fer:

$ git add .

per afegir-ho tot

IMPORTANT: OCO! al afegir codi! Mireu de no afegir dades sensibles si es tracta d'un repositori públic. Cal prestar especial atenció a fitxer de conexió a base de dades

També cal fer commit:

$ git commit -m 'initial commit comment'

I cal crear el repositori remove:

$ git remote add origin URL_DEL_REPOSITORI

I fer un push:

$ git push origin master

Compte si el repositori remot no esta buit (per exemple només que tingui un fitxer README, típic a github), primeu feu un pull i després el push:

$ git pull origin master
$ git push origin master

Recursos:

Desfer els últims canvis locals (tornar al últim commit)

$ git reset --hard

Subprojects

TODO

A subproject is a generic term for one of three types of nesting:

  • Submodules provide semi-fixed references from the superproject into subprojects and are integrated into git. It is best used when the subproject:

is developed by someone else, is not under the administrative control of the superproject and follows a different release cycle. contains code shared between superprojects (especially when the intention is to propagate bugfixes and new features back to other superprojects). separates huge and/or many files that would hurt performance of everyday git commands.

  • Subtrees causes the subproject repository to be imported into the superproject's repository to be a native part of the repository with full history, typically in a specific subdirectory of the superproject.
  • Wrappers, which provide multi-repository management functionality to a superproject with associated subprojects.The best advertised on this page and arguably the simplest is gitslave which provides a command called `gits` which under most circumstances takes the same arguments as `git` and performs the same job, except over all repositories registered with the superproject. Another tool is Google's repo which is used for Android development but does not appear to be well (or at least obviously) documented for non-Android purposes.

Recursos:

Submodules

Els submòduls permeten gestionar subprojectes dins d'un projecte. Un exemple típic són les llibreries. Suposeu que esteu desenvolupant un projecte vostre propi (evidentment amb el seu corresponent repositori git) però a més el vostre projecte utilitza una llibreria de tercers amb el seu propi repositori git. En aquest cas pot ser útil gestionar la llibreria de tercers com un submodul git.

La comanda per gestionar els submòduls és:

$ git submodule

per afegir un submòdul:


$ git add

La informació es guarda al fitxer:

$ cat .gitmodules

IMPORTANT: Oco però que a Internet s'informa en diverses webs dels problemes d'utilitzar els mòduls. En alguns casos es recomana git subtrees

Subtree

Recursos:

wrappers

IDEs

Eclipse

Egit

Egit

EGit is an Eclipse Team provider for the Git version control system. Git is a distributed SCM, which means every developer has a full copy of all history of every revision of the code, making queries against the history very fast and versatile.

The EGit project is implementing Eclipse tooling on top of the JGit Java implementation of Git.

URL del plugin:

http://download.eclipse.org/egit/updates 

Recursos:

Documentació

icones i estats dels fitxers

EstatsEgitIIcones.png
  • added to index - staged but not yet committed (index és un altre nom utilitzat per a l'staging area)
  • dirty - file has changed since the last commit
  • ignore - flagged to be ignored by Git
  • staged - staged to be included in the next commit
  • tracked - commit and not changed
  • untracked - neither staged nor committed

A més al nom del projecte es mostra un número que indica el número de commits que s'han fet en local i no pas en remot (número al costat de la fletxa amunt)

EstatsEgitIIcones2.png

No trobarem una comanda similar a:

$ git status

Per què amb les integracions abans comentades ja ens podem fer una idea de l'estat. De fet:

$ git status
# On branch master
# Your branch is ahead of 'original/master' by 2 commits.
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   GIT_HELP
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	.buildpath
#	.project
#	.settings/
no changes added to commit (use "git add" and/or "git commit -a")

Vegeu com:

Your branch is ahead of 'original/master' by 2 commits.  --> és el mateix que l'indicador que surt al titol de projecte (mostra el número de commits locals que no s'han fet en remot)

Els fitxers untracked que apareixen són els típics fitxers ocults d'Eclipse (com a tals no apareixen a l'Eclipse, i es poden afegir a gitignore)

Zend Studio

Afegir claus:

Open up Zend Studio’s preferences window Navigate to General->Network Connections->SSH2 Select the key management tab and click “Generate RSA key” You will see that the text box is now filled with “ssh-rsa” and then a bunch of giberish. That is your new public keyCreating SSH Key Click the “Save Private Key” Function and confirm that you want to save it without a passphrase Login to your GitHub account and go to Account Settings->SSH Public Keys Click add a public key and enter the name (e.g. my laptop) and paste t

http://clintberry.com/2011/zend-studio-and-github/

Recursos:

http://files.zend.com/help/Zend-Studio/content/working_with_git_and_github.htm

Dreamweaver

Repositoris

GITHUB

TODO

GITORIOUS

Afegir un projecte com alumne

IMPORTANT: Canvieu COGNOM1NOM1alumne pel que correspongui en el vostre cas

$ cd ~ && mkdir GIT && cd GIT
$ git clone git@gitorious.org:2dam201213/alumnes.git
$ cd alumnes/
$ git remote add master git@gitorious.org:test2dam/alumnes.git
$ mkdir COGNOM1NOM1alumne
$ touch COGNOM1NOM1alumne/README.txt

Poseu un text qualsevol a:

$ joe COGNOM1NOM1alumne/README.txt

I ara:

$ git add .
$ git commit -a
$ git push --all

Aquestes tres últimes passes són les que us cal fer cada cop que modifiqueu el repositori local. Ara ja podeu afegir fitxers i carpetes a la vostra carpeta d'alumnes per tal de penjar els projectes

Afegir un projecte

$ git clone git@gitorious.org:test2dam/test2dam.git
$ cd test2dam/
$ git remote add master git@gitorious.org:test2dam/test2dam.git
$ mkdir codiprova
$ touch codiprova/a
$ git add .
$ git commit -a
$ git push --all

Fer un checkout d'un sol fitxer i una versió/commit especifica

$ git log fitxer

Sí és un fitxer esborrat utilitzeu:

$ git log -- fitxer

Apunteu el hash i l'utilitzeu amb:

$ git checkout HASH fitxer

exemple:

$ git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 index.php

git diff

Comparar versió actual (HEAD) i commit anterior(HEAD^)

$ git diff HEAD^ HEAD

o

$ git difftool -t meld HEAD^ HEAD

Mostrar els canvis dels fitxers que encara no han estat afegits al repositori local (not stagged)

$ git diff HEAD

Mostrar els canvis en un repositori remot abans de fer un pull

Cal tenir en compte que la comanda:

$ git pull

és equivalent a fer un primer un:

$ git fetch

i després un:

$ git merge

Tenint en compte això abans de fer un pull es pot fer:

$ git fetch origin

I comparar amb:

$ git diff master origin/master

Si us convenen els canvis ara podeu fer el pull o només:

$ git merge


Mostrar els canvis repositori local pendents de push

$ sudo git diff origin/master..HEAD

IMPORTANT: Abans cal haver fer el commit dels canvis. Vegeu el següent apartat

Mostrar els canvis pendents de commit

IMPORTANT: Es fitxer ha d'estar afegit a GIT, és a dir stagged

$ sudo git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   application/controllers/skeleton_auth/ebre_escool_auth.php
#	modified:   application/modules/managment/models/managment_model.php

Amb:

$ git diff --staged

Us mostraa els canvis que heu fet en local i que estan pendents de commit.

Meld

Al fitxer:

~/.gitconfig fixed it for me:

Poseu:

[merge]
       tool = mymeld
[mergetool "mymeld"]
       cmd = meld "$LOCAL" "$MERGED" "$REMOTE"


Creeu un script:

$ joe ~/diff.ppy
#!/usr/bin/python

import sys
import os

os.system('meld "%s" "%s"' % (sys.argv[2], sys.argv[5]))

Ara:

$ git config --global diff.external /home/sergi/diff.py
$ git diff

Repositoris remots

En un repositori local/working directory:

$ git remote -v
origin	https://github.com/acacha/ebre-inventory.git (fetch)
origin	https://github.com/acacha/ebre-inventory.git (push)

Si el directory no està inicialitzat:

$ git remote
fatal: Not a git repository (or any of the parent directories): .git

Si inicialitzeu:

$ git init
$ git remote

Ara no us torna res perquè no hi ha cap repositori remot especificat. Per afegir un repositori remove utilitzeu remote add:

$ git remote add origin https://github.com/username/Hello-World.git

ara:

$ git remote
origin

o:

$ git remove -v
origin	https://github.com/username/Hello-World.git (fetch)
origin	https://github.com/username/Hello-World.git (push)

O més info amb show:

$ sudo git remote show origin
* remote origin
 Fetch URL: https://github.com/acacha/ebre-inventory.git
 Push  URL: https://github.com/acacha/ebre-inventory.git
 HEAD branch: master
 Remote branch:
   master tracked
 Local branch configured for 'git pull':
   master merges with remote master
 Local ref configured for 'git push':
   master pushes to master (local out of date)

També hi ha les opcions rm i rename:

$ git remote rename origin paul
$ git remote
paul

o

$ git remote rm paul
$ git remote
origin

Finalment tenir en compte que existeix:

$ git remote update

que és similar a fetch:

$ git fetch --all 

Es a dir fa un fetch de tots els repositoris remots.

Recursos:

Comprovar si hi ha canvis a repositoris remots

$ sudo git fetch -v --dry-run

Revertir un commit

Hi ha dos opcions:

  • Tornar a fer un nou commit que deixi el fitxer tal i com estava en un anterior commit
  • Utilitzar revert:
$ git log fitxer

Apunteu el número de commit i feu

$ git revert 42f5eb74c595f4c2391aa192f475ecbee3a8c191

Recursos:

Forks

Actualitzar un fork amb el upstream

Ignorar canvis a un fitxer local (.git/info/exclude) i --assume-unchanged

Podeu utilitzar el fitxer .git/info/exclude i --assume-unchanged

$ echo path/to/file >> .git/info/exclude
$ git update-index --assume-unchanged path/to/file

Per tornar a fer el track dels canvis del fitxer:

$ git update-index --no-assume-unchanged path/to/file

Per mostrar els fitxers que estan a l'estat assume-unchanged:

# git ls-files -v  | grep ^[a-z]
h application/config/config.php
h application/config/inventory.php
h application/logs/audit.log
h application/logs/test.png-errors.txt
h index.php


Recursos:

Fitxers de configuració i dades sensibles

Patró: al repositori fitxer exemple amb diferent nom i en local fitxer untracked

Recursos:

cached

echo "FILE_NAME" >> .gitignore
git rm --cached FILE_NAME
git add -u
git commit -m "removing files from version control"
 
git pull
git push

Recursos:

Using git hooks

Recursos: http://blog.bossylobster.com/2011/10/protecting.html

Resol·lució de problemes

Mostrar la història d'un fitxer esborrat

Cal utilitzar log però afegint --:

$ git log -- index.php

non-fast-forward-errors on push

https://help.github.com/articles/dealing-with-non-fast-forward-errors

Vegeu també

Enllaços externs