nuestro de cada día
Nociones y algo más
Alan Descoins
Tryolabs, 2014
Objetivos
● Entender mejor lo que hacemos diariamente
● Hacer menos preguntas (entender el man)
● Mejorar algunas prácticas
● Cometer menos errores
● Hacer algo super puntual ;)
Orígenes y filosofía
● 2005, kernel de Linux
● Eficiencia, diseño simple
● Desarrollo no lineal (miles de
branches en paralelo)
● Completamente distribuído
Distribuído
● Casi toda operación es
local
● Todas las máquinas
tienen TODA la
información
● Contraste SVN, CVS,
etc.
Algo de teoría
● git init inicializa un repositorio
● Crea un único directorio .git en la raíz (no contamina)
● Mini filesystem
● Snapshots, no diferencias!
Git y el contenido
● Tracking de contenido, NO archivos
● Vocabulario: tracked / untracked
● Objetos de git
○ Blob (contenido)
○ Tree (estructura)
○ Commit (apunta a un tree, + data)
○ Tag (apunta a un commit, + data)
SHA-1
Blob
● Un archivo por “contenido”
● SHA-1 del contenido (zlib) + un
header
● Inicialmente, loose object
● Luego packfile (eficiencia,
heurísticas…)
● Ejemplo: find .git/objects -type f
Tree
● Como una estructura de
directorios
● Punteros a blobs u otros trees
● Representa un snapshot
completo del estado
● Ejemplo: git ls-tree <sha-1>
Commit
● Información sobre los trees
● Quién, cuándo, por qué guardó el tree
● Apunta al tree de “más arriba” (top level) del
proyecto
● Jerarquía de árbol
● También SHA-1, diferente hash que el tree
al que apunta
Commit (2)
Tags
● Puntero a un commit
● Información adicional, firma
● Para no tener que acordarse del
SHA-1...
La santa Trinidad
Un contenido puede estar en tres estados
● Committed
● Modified
● Staged
La santa Trinidad (2)
Tres partes un proyecto:
● Working directory
● Staging area (o index)
● .git (repository)
Comandos básicos
● git add - agrega al index (staging)
● git commit - guarda el index actual con el autor,
mensaje, fecha, etc.
● git status - muestra los archivos con diferencias en
working dir, staging, y los untracked
● git diff - lo que cambió pero no está staged
● git diff --cached - lo que va para el próximo commit
● git log
Saltear el staging
● A veces, puede ser más fácil saltear el
staging
● git commit -a | git commit <archivo>
● Agregan automáticamente al staging, luego
commitean
Branches
● Simplemente un puntero a un commit
● Tan rápido como escribir 41 caracteres a un
archivo (SHA-1 + n)
● Por defecto master
● Puntero especial HEAD (branch actual)
● Ejemplo: cat .git/HEAD
Branches (2)
● git checkout
para cambiarse
de branch
Referencias
● El puntero HEAD es un caso particular
● Los tags también: “una branch inamovible”
(lightweight tags)
Ejemplo: find .git/refs
Remotes
● No hay servidor central
● Se pueden agregar varios remotes, copias
externas del repositorio (URL)
● El famoso origin :)
Branches remotas
● Guardan el estado de las branches en los repositorios
remotos
● Son locales, pero no se pueden mover; solo cuando se
hacen operaciones en la red (ej. git fetch).
● Forma <remote>/<branch>
Ejemplo: cat .git/refs/remotes/origin/master
Fetch, push
● git fetch - sincroniza y actualiza branches remotas
(mueve punteros)
● Ej. git fetch <remote>
● git pull - equivalente a git fetch y luego git merge,
mergea la branch local con cambios en la remota
● git push - actualiza branch remota con lo local
● Ej. git push <remote> <branch>
Tracking branches
● Branches locales pueden “seguir” remotas
● Dos posibilidades:
○ git checkout --track <remote>/<branch>
○ git push --set-upstream <remote> <branch>
● Así, al pushear no hay que escribir el
nombre del remote y la branch :)
Merges
● Fast-forward: git es
inteligente y solo necesita
mover un puntero
● Integrar cambios de una branch en otra
Merges (2)
● Three way merge: commit no es ancestro
directo de lo que se mergea (no lineal)
● Git determina el mejor ancestro común
● Se crea un merge commit, especial pues
tiene más de un padre
● Conflictos...
Three way merge
Rebasing
● Otra forma de introducir cambios de una
branch en otra
● Rewind & replay, reescribe los commits
● A partir de un ancestro común
● Historia queda siempre lineal, más allá de
que originalmente fue en paralelo
Rebasing (2)
● git rebase <new-base>
mueve los commits de la
branch actual a la nueva
base
● git rebase -i <new-base>
selecciona acciones para
cada commit
● git pull --rebase
Reglas doradas
● Nunca hacer rebase de una branch que está
pusheada, o pulleaste de otra persona
○ Commits duplicados si se hace merge
○ Discutible: si la branch remota la usa solo uno a modo de backup.
○ Usar git push --force, si se sabe que otros developers no trabajan en
la branch.
● Si se hace rebase para traer cambios de otros
developers al local, hacerlo tan seguido como sea
posible.
Rebase vs Merge
¿Por qué rebase?
● Historial limpio
● Colaboración open-source, muchos lo exigen
● Más fácil code review
¿Por qué merge?
● Más fácil solucionar conflictos
● Menor riesgo
git reset
● Se usa a menudo
● Mal usado, puede generar pérdida de
datos (workdir unsafe)
● Tres opciones más usadas:
○ --soft
○ --mixed
○ --hard
git reset...
● mueve la branch a la que apunta HEAD para que
apunte al commit destino (frena si --soft)
● luego hace que el staging se vea como eso (frena si --
mixed, opción por defecto)
● luego hace que el working dir se vea como eso (si --
hard, es workdir usafe!)
Ejemplos git reset
● Con HEAD en branch dev, hago git reset master
○ ahora dev y master apuntan al mismo commit
● Con HEAD en branch master, hago git reset --hard
origin/master
○ ahora mi branch master es idéntica a la remote
(descartar cambios locales)
● git reset --soft HEAD~
○ Deshace el último commit sin perder cambios
Unstaging de archivos
● Al hacer git reset <file> no especifica branch
ni commit SHA
● Equivalente a git reset --mixed HEAD <file>
● Saca un archivo particular del staging,
opuesto de git add :)
git checkout
● git checkout <branch> es superficialmente
parecido a git reset --hard <branch>
● Dos diferencias:
○ Workdir safe! :D Chequea por pérdida de datos.
○ reset mueve la branch a la que apunta HEAD,
checkout mueve el puntero HEAD.
git checkout de archivo
● git checkout <branch> <file>
○ Al igual que reset, ahora no tiene sentido que mueva
HEAD. Reemplaza solamente <file> en workdir
(workdir usafe!).
○ Sería lo mismo que git reset --hard <branch> <file>
○ Pero ese comando no existe :)
Situaciones comunes (1)
● “Necesito hacer pull pero tengo cambios en
los que estoy trabajando y no quiero
commitear todavía”
○ git stash
○ Es un stack
○ Vaciarlo con git stash pop.
Situaciones comunes (2)
● “Hay un bug en una branch, necesito saber
qué commit lo introdujo”
○ git bisect
○ Búsqueda binaria, conducida por git. Muy fácil!
○ git bisect start
git bisect bad <commit>
git bisect good <commit>
● Probamos en cada paso (git hace checkout)
Situaciones comunes (3)
● “Hice uno (o varios) commits en la branch
equivocada, todavía no pushee!”
○ Si la branch correcta no existe
■ git checkout -b <branch correcta>
■ git reset sobre vieja branch
○ Si la branch ya existía
■ git cherry-pick (o git rebase --onto)
■ git reset sobre vieja branch
Situaciones comunes (4)
● “Tengo muchos cambios en un archivo y
solo quiero comittear parte de ellos”
○ git add -p o git commit -p
○ git va a preguntar por cada parte, si queremos
agregarla o no
Situaciones comunes (5)
● “Necesito cambiar unos commits”
● “Necesito borrar unos commits”
● “Necesito cambiar de orden unos commits”
○ git rebase -i (--interactive)
○ Fácil de usar
○ Reescribiendo la historia, preguntándonos qué
queremos hacer por cada commit
Situaciones comunes (6)
● “Estoy haciendo un merge con muchos
conflictos y quiero volver a como estaba
antes de comenzarlo”
○ git merge --abort
(Imágenes de git-scm y demás ;) )
No aprendió git

El git nuestro de cada dia

  • 1.
    nuestro de cadadía Nociones y algo más Alan Descoins Tryolabs, 2014
  • 2.
    Objetivos ● Entender mejorlo que hacemos diariamente ● Hacer menos preguntas (entender el man) ● Mejorar algunas prácticas ● Cometer menos errores ● Hacer algo super puntual ;)
  • 3.
    Orígenes y filosofía ●2005, kernel de Linux ● Eficiencia, diseño simple ● Desarrollo no lineal (miles de branches en paralelo) ● Completamente distribuído
  • 4.
    Distribuído ● Casi todaoperación es local ● Todas las máquinas tienen TODA la información ● Contraste SVN, CVS, etc.
  • 5.
    Algo de teoría ●git init inicializa un repositorio ● Crea un único directorio .git en la raíz (no contamina) ● Mini filesystem ● Snapshots, no diferencias!
  • 6.
    Git y elcontenido ● Tracking de contenido, NO archivos ● Vocabulario: tracked / untracked ● Objetos de git ○ Blob (contenido) ○ Tree (estructura) ○ Commit (apunta a un tree, + data) ○ Tag (apunta a un commit, + data) SHA-1
  • 7.
    Blob ● Un archivopor “contenido” ● SHA-1 del contenido (zlib) + un header ● Inicialmente, loose object ● Luego packfile (eficiencia, heurísticas…) ● Ejemplo: find .git/objects -type f
  • 8.
    Tree ● Como unaestructura de directorios ● Punteros a blobs u otros trees ● Representa un snapshot completo del estado ● Ejemplo: git ls-tree <sha-1>
  • 9.
    Commit ● Información sobrelos trees ● Quién, cuándo, por qué guardó el tree ● Apunta al tree de “más arriba” (top level) del proyecto ● Jerarquía de árbol ● También SHA-1, diferente hash que el tree al que apunta
  • 10.
  • 11.
    Tags ● Puntero aun commit ● Información adicional, firma ● Para no tener que acordarse del SHA-1...
  • 12.
    La santa Trinidad Uncontenido puede estar en tres estados ● Committed ● Modified ● Staged
  • 13.
    La santa Trinidad(2) Tres partes un proyecto: ● Working directory ● Staging area (o index) ● .git (repository)
  • 14.
    Comandos básicos ● gitadd - agrega al index (staging) ● git commit - guarda el index actual con el autor, mensaje, fecha, etc. ● git status - muestra los archivos con diferencias en working dir, staging, y los untracked ● git diff - lo que cambió pero no está staged ● git diff --cached - lo que va para el próximo commit ● git log
  • 15.
    Saltear el staging ●A veces, puede ser más fácil saltear el staging ● git commit -a | git commit <archivo> ● Agregan automáticamente al staging, luego commitean
  • 16.
    Branches ● Simplemente unpuntero a un commit ● Tan rápido como escribir 41 caracteres a un archivo (SHA-1 + n) ● Por defecto master ● Puntero especial HEAD (branch actual) ● Ejemplo: cat .git/HEAD
  • 17.
    Branches (2) ● gitcheckout para cambiarse de branch
  • 18.
    Referencias ● El punteroHEAD es un caso particular ● Los tags también: “una branch inamovible” (lightweight tags) Ejemplo: find .git/refs
  • 19.
    Remotes ● No hayservidor central ● Se pueden agregar varios remotes, copias externas del repositorio (URL) ● El famoso origin :)
  • 20.
    Branches remotas ● Guardanel estado de las branches en los repositorios remotos ● Son locales, pero no se pueden mover; solo cuando se hacen operaciones en la red (ej. git fetch). ● Forma <remote>/<branch> Ejemplo: cat .git/refs/remotes/origin/master
  • 21.
    Fetch, push ● gitfetch - sincroniza y actualiza branches remotas (mueve punteros) ● Ej. git fetch <remote> ● git pull - equivalente a git fetch y luego git merge, mergea la branch local con cambios en la remota ● git push - actualiza branch remota con lo local ● Ej. git push <remote> <branch>
  • 22.
    Tracking branches ● Brancheslocales pueden “seguir” remotas ● Dos posibilidades: ○ git checkout --track <remote>/<branch> ○ git push --set-upstream <remote> <branch> ● Así, al pushear no hay que escribir el nombre del remote y la branch :)
  • 23.
    Merges ● Fast-forward: gites inteligente y solo necesita mover un puntero ● Integrar cambios de una branch en otra
  • 24.
    Merges (2) ● Threeway merge: commit no es ancestro directo de lo que se mergea (no lineal) ● Git determina el mejor ancestro común ● Se crea un merge commit, especial pues tiene más de un padre ● Conflictos...
  • 25.
  • 26.
    Rebasing ● Otra formade introducir cambios de una branch en otra ● Rewind & replay, reescribe los commits ● A partir de un ancestro común ● Historia queda siempre lineal, más allá de que originalmente fue en paralelo
  • 27.
    Rebasing (2) ● gitrebase <new-base> mueve los commits de la branch actual a la nueva base ● git rebase -i <new-base> selecciona acciones para cada commit ● git pull --rebase
  • 28.
    Reglas doradas ● Nuncahacer rebase de una branch que está pusheada, o pulleaste de otra persona ○ Commits duplicados si se hace merge ○ Discutible: si la branch remota la usa solo uno a modo de backup. ○ Usar git push --force, si se sabe que otros developers no trabajan en la branch. ● Si se hace rebase para traer cambios de otros developers al local, hacerlo tan seguido como sea posible.
  • 29.
    Rebase vs Merge ¿Porqué rebase? ● Historial limpio ● Colaboración open-source, muchos lo exigen ● Más fácil code review ¿Por qué merge? ● Más fácil solucionar conflictos ● Menor riesgo
  • 30.
    git reset ● Seusa a menudo ● Mal usado, puede generar pérdida de datos (workdir unsafe) ● Tres opciones más usadas: ○ --soft ○ --mixed ○ --hard
  • 31.
    git reset... ● muevela branch a la que apunta HEAD para que apunte al commit destino (frena si --soft) ● luego hace que el staging se vea como eso (frena si -- mixed, opción por defecto) ● luego hace que el working dir se vea como eso (si -- hard, es workdir usafe!)
  • 32.
    Ejemplos git reset ●Con HEAD en branch dev, hago git reset master ○ ahora dev y master apuntan al mismo commit ● Con HEAD en branch master, hago git reset --hard origin/master ○ ahora mi branch master es idéntica a la remote (descartar cambios locales) ● git reset --soft HEAD~ ○ Deshace el último commit sin perder cambios
  • 33.
    Unstaging de archivos ●Al hacer git reset <file> no especifica branch ni commit SHA ● Equivalente a git reset --mixed HEAD <file> ● Saca un archivo particular del staging, opuesto de git add :)
  • 34.
    git checkout ● gitcheckout <branch> es superficialmente parecido a git reset --hard <branch> ● Dos diferencias: ○ Workdir safe! :D Chequea por pérdida de datos. ○ reset mueve la branch a la que apunta HEAD, checkout mueve el puntero HEAD.
  • 35.
    git checkout dearchivo ● git checkout <branch> <file> ○ Al igual que reset, ahora no tiene sentido que mueva HEAD. Reemplaza solamente <file> en workdir (workdir usafe!). ○ Sería lo mismo que git reset --hard <branch> <file> ○ Pero ese comando no existe :)
  • 36.
    Situaciones comunes (1) ●“Necesito hacer pull pero tengo cambios en los que estoy trabajando y no quiero commitear todavía” ○ git stash ○ Es un stack ○ Vaciarlo con git stash pop.
  • 37.
    Situaciones comunes (2) ●“Hay un bug en una branch, necesito saber qué commit lo introdujo” ○ git bisect ○ Búsqueda binaria, conducida por git. Muy fácil! ○ git bisect start git bisect bad <commit> git bisect good <commit> ● Probamos en cada paso (git hace checkout)
  • 38.
    Situaciones comunes (3) ●“Hice uno (o varios) commits en la branch equivocada, todavía no pushee!” ○ Si la branch correcta no existe ■ git checkout -b <branch correcta> ■ git reset sobre vieja branch ○ Si la branch ya existía ■ git cherry-pick (o git rebase --onto) ■ git reset sobre vieja branch
  • 39.
    Situaciones comunes (4) ●“Tengo muchos cambios en un archivo y solo quiero comittear parte de ellos” ○ git add -p o git commit -p ○ git va a preguntar por cada parte, si queremos agregarla o no
  • 40.
    Situaciones comunes (5) ●“Necesito cambiar unos commits” ● “Necesito borrar unos commits” ● “Necesito cambiar de orden unos commits” ○ git rebase -i (--interactive) ○ Fácil de usar ○ Reescribiendo la historia, preguntándonos qué queremos hacer por cada commit
  • 41.
    Situaciones comunes (6) ●“Estoy haciendo un merge con muchos conflictos y quiero volver a como estaba antes de comenzarlo” ○ git merge --abort
  • 42.
    (Imágenes de git-scmy demás ;) ) No aprendió git