git-intro



git-intro

0 0


git-intro

Intro a Git

On Github patok / git-intro

Introducción a GIT

Created by @patokeilty

Contenido

  • Intro
  • Operaciones básicas
  • Branching y merging
  • Repos remotos
  • References
  • Ejemplos prácticos de uso

Qué es git?

  • es un sistema de control de versiones de código abierto
  • diseñado para ser: veloz, simple, distribuido, que soporte desarrollo no lineal (muchas ramas en paralelo),maneje grandes proyectos de manera eficiente (tiempo y espacio)
  • se desarrolló como control de versiones para el kernel del SO Linux en el 2005
  • su autor es Linus Torvalds (autor tb del kernel linux)
  • ! segunda acepción: un rastreador estúpido/simple de info - stupid content tracker

Taxonomías SCM

Tipo almacenamiento:

  • diffs/deltas
  • DAG/snapshots

Taxonomías SCM

Deltas vs Snapshots

Taxonomías SCM

Clasificación según arquitectura

  • local: restringido a la máquina de trabajo
  • centralizado: cliente-servidor, única fuente autorizada
  • distribuido: red de pares, hay múltiples copias in-sync

Taxonomías SCM

Matriz de clasificación

Concepto principal : commit!

el commit: es una foto del codebase que tiene los sig. attributos:

  • commit ID
  • autor
  • fecha
  • comentario
  • una historia (a través de sus padres)

Características

operaciones locales (copia local del repo, no se necesita estar conectado): checkouts, commits, branching, análisis historia integridad: cada objeto en la bbdd posee un hash (SHA1 - hex de 40 dígitos -criptográficamente seguro ) estructura simple de almacenamiento: siempre se escriben datos, no se actualizan files 3 estados: modificado, en staging (listo para commitear), commiteado

Estados de un file

Comandos básicos

Conectándose a un repo

  • inicializando local

    $ git init

  • clonar un repo remoto

    $ git clone git://github.com/schacon/grit.git

.git directory

$ tree .git
.git
|-- config
|-- description
|-- HEAD
|-- hooks
|   |-- commit-msg.sample
|-- index
|-- info
|   `-- exclude
|-- objects
|   |-- info
|   `-- pack
`-- refs
|-- heads
`-- tags
			

Chequeando estado

nada que commitear

$ git status
# On branch master
nothing to commit (working directory clean)
			

Chequeando estado

tengo modificaciones

$ vim README
...
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   README
nothing added to commit but untracked files present (use "git add" to track)

		

Agregando nuevos files

$ git add README

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   README
#
			

Subiendo modificaciones a staging

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
# 
#   new file:   README
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
# 
#   modified:   benchmarks.rb
# 

$ git add benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
# 
#   new file:   README
#   modified:   benchmarks.rb
# 
			

Ignorando cambios (.gitignore)

$ cat .gitignore 
*target/
*.settings/
*.classpath
*.project
*bin/
		

# a comment - this is ignored
*.a       # no .a files
!lib.a    # but do track lib.a, even though you're ignoring .a files above
/TODO     # only ignore the root TODO file, not subdir/TODO
build/    # ignore all files in the build/ directory
doc/*.txt # ignore doc/notes.txt, but not doc/server/arch.txt
			

Viendo cambios con mas detalle

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   README
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#   modified:   benchmarks.rb
#
			

$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 3cb747f..da65585 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -36,6 +36,10 @@ def main
       @commit.parents[0].parents[0].parents[0]
     end

+        run_code(x, 'commits 1') do
+          git.commits.size
+        end
+
     run_code(x, 'commits 2') do
       log = git.commits('master', 15)
       log.size
			

Viendo los cambios (staging o cacheados)

$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README2
@@ -0,0 +1,5 @@
+grit
+ by Tom Preston-Werner, Chris Wanstrath
+ http://github.com/mojombo/grit
+
+Grit is a Ruby library for extracting information from a Git repository     
			

Commiteando los cambios

$ git 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
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   README
#       modified:   benchmarks.rb
~
~
~
".git/COMMIT_EDITMSG" 10L, 283C
			

Borrando

$ git rm grit.gemspec
$ rm 'grit.gemspec'
$ git status
# On branch master
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       deleted:    grit.gemspec
#

Renombrando o moviendo

$ git mv README.txt README
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       renamed:    README.txt -> README
#
			

git es suficientemente inteligente para detectarlo si no se lo informamos

$ mv README.txt README
$ git rm README.txt
$ git add README
			

Deshaciendo último commit: commit --amend

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
			

Deshaciendo cambios: reset

supongamos este caso ...

$ git add .
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   README.txt
#       modified:   benchmarks.rb
#
			

... y queremos volver para atrás y no commitear benchmarks.rb

$ git reset HEAD benchmarks.rb
benchmarks.rb: locally modified

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   README.txt
#
# 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:   benchmarks.rb
#
			

Revisando la historia

git log

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon 
Date:   Mon Mar 17 21:52:11 2008 -0700

changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon 
Date:   Sat Mar 15 16:40:33 2008 -0700

removed unnecessary test code

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon 
Date:   Sat Mar 15 10:31:28 2008 -0700

first commit
			@gee-mail.com>@gee-mail.com>@gee-mail.com>

otras alternativas de formateo del output:

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon 
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

 Rakefile |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon 
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

 lib/simplegit.rb |    5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon 
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

 README           |    6 ++++++
 Rakefile         |   23 +++++++++++++++++++++++
 lib/simplegit.rb |   25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)
			@gee-mail.com>@gee-mail.com>@gee-mail.com>

muestra los files y estadísticas de cambios

otras alternativas de formateo del output:

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon 
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,5 +5,5 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon 
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end
\ No newline at end of file

			@gee-mail.com>@gee-mail.com>

muestra las diffs de cada commit, para los últimos 2!

Revisando la historia

..visualmente ;-)

Salvando el trabajo en progreso

usando el stash

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#

$ git stash save
Saved working directory and index state \
  "WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")
			

usando el stash

$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
			

$ git stash apply
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   index.html
#      modified:   lib/simplegit.rb
#
			

Si se te queman los papeles ...

Help!

$ git help
usage: git [--version] [--exec-path[=]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=] [--work-tree=] [--namespace=]
           [-c name=value] [--help]
            []

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and merge with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

See 'git help ' for more information on a specific command.

			

$ git help status
$ git help commit
			

Branching

Qué es un rama (branch) en Git?

  • Un branch en Git es un puntero ágil y móvil a un commit.
  • Al crear un repositorio, Git te provee un branch que "apunta" al último commit. Por default tiene por nombre master.
  • Puedes crear tus propios branches/ramas, a partir de cualquier commit.
  • A medida que realices nuevos commits, ese puntero se irá moviendo hacia adelante automáticamente.

Branching básico

Supongamos el siguiente escenario:

estamos trabajando en un proyecto que ya posee algunos commits arrancamos a desarrollar una nueva story creando para ello una nueva rama de nombre "iss53" llega un requerimiento de resolver un bug de alta prioridad necesitamos abandonar momentaneamente la story para proveer un hotfix creamos un branch "hotfix", y una vez probado nuestro fix, se debe mergear e instalarse en producción volver a trabajar en la story

Historia del proyecto actual

Nueva rama iss53

$ git checkout -b iss53
Switched to a new branch "iss53"
                      

Commiteamos en la nueva rama iss53

$ vim index.html
...
$ git commit -a -m 'added a new footer [issue 53]'
                      

observar como se mueve hacia adelante la referencia

Volviendo a master para trabajar en el fix

$ git checkout master
Switched to branch "master"
                         

Git resetea el directorio de trabajo para que sea el mismo que corresponde al último commit en master.

Creamos el branch hotfix, y armamos el fix

$ git checkout -b 'hotfix'
Switched to a new branch "hotfix"
    
    
$ vim index.html
...
$ git commit -a -m 'fixed the broken email address'
[hotfix]: created 3a0874c: "fixed the broken email address"
1 files changed, 0 insertions(+), 1 deletions(-)
                        

Listos para mergear el hotfix en master

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast forward
README |    1 -
1 files changed, 0 insertions(+), 1 deletions(-)
                        

listo para deployar en producción y volver a la story!

Fast forwarding branches

Una rama que acaba de ser actualizada con commits mas recientes, es susceptible de hacerle fast-forwarding cuando sus commits son ancestros de los nuevos commits.

Vuelvo a la story

borra branch del hotfix

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
                        

switchea al branch iss53

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
...
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53]: created ad82d7a: "finished the new footer [issue 53]"
1 files changed, 1 insertions(+), 0 deletions(-)
                

Mergeando

Cómo puedo llevar la nueva funcionalidad al master?

$ git checkout master
$ git merge iss53
Merge made by recursive.
 README |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
                        

Mergeando: en caso de conflicto

Cuando los algoritmos de mergeo de Git no pueden resolver automáticamente avisan

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

$ git status
index.html: needs merge
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   unmerged:   index.html
#

<<<<<<< HEAD
contact : email.support@github.com
=======
please contact us at support@github.com
>>>>>>> iss53

Mergeando: en caso de conflicto

Se debe resolver manualmente o empleando alguna herramienta para merge (mergetool)

$ vim index.html

$ git add index.html

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#
                        

Obteniendo info de los branches

Algunos comandos útiles

$ git branch -v
iss53   93b412c fix javascript issue
* master  7a98805 Merge branch 'iss53'
testing 782fd34 add scott to the author list in the readmes
                        

para obtener los branches locales

$ git branch --merged
iss53
* master
                        

informa los branches que están mergeados en branch actual

$ git branch --contains e5c2d6ec
* master
                        

imprime los branches que contienen el commit e5c2d6ec...

Branches: estrategias mas usadas

Branches de larga permanencia

Topic branches por el contrario tiene muy corta vida

Branches: estrategias mas usadas

Branches por tópico

Topic branches por el contrario tiene muy corta vida

Rebasing vs Merge

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
                        

toma el commit C3 y lo reaplica en el branch generando un nuevo commit C3'

Respositorios remotos

Los repositorios remotos permiten compartir el código, básicamente son copias de ntra. base de objetos, para _sincronizarlos_ usamos:

push, fetch (pull)

Mostrando repos remotos (remote -v)

$ git remote -v
origin  git://github.com/schacon/ticgit.git
                         

Agregando repo remoto (remote add)

$ git remote
origin
$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin  git://github.com/schacon/ticgit.git
pb  git://github.com/paulboone/ticgit.git
                        

Sincronizando copia local del repo remoto (fetch)

$ git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit
                        

Pusheando/subiendo cambios al repo remoto (push)

$ git push origin master
                        

Info sobre repo remoto (remote show)

$ git remote show origin
* remote origin
  URL: git://github.com/schacon/ticgit.git
  Remote branch merged with 'git pull' while on branch master
    master
  Tracked remote branches
    master
    ticgit
                        

Repositorios Remotos

Ejemplos de uso

Ejemplos de uso

Resumen

Conclusiones

  • rápido y eficiente (las operaciones mas usadas son locales)
  • todos tienen una copia, por ende hay muchos backups ;)
  • no se necesita estar conectado para:
    • ver la historia de un file
    • crear un nueva rama o switchear ramas
    • mergear código entre branches
    • commitear código
    • ver diferencias entre versiones
    • obtener cualquier versión de un file

Material Referencia

Libros

Downloads, websites

Videos