1. nuestro de cada día
Nociones y algo más
Alan Descoins
Tryolabs, 2014
2. Objetivos
● Entender mejor lo 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 toda operació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 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
7. 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
8. Tree
● Como una estructura de
directorios
● Punteros a blobs u otros trees
● Representa un snapshot
completo del estado
● Ejemplo: git ls-tree <sha-1>
9. 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
11. Tags
● Puntero a un commit
● Información adicional, firma
● Para no tener que acordarse del
SHA-1...
12. La santa Trinidad
Un contenido 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
● 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
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 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
18. Referencias
● El puntero HEAD es un caso particular
● Los tags también: “una branch inamovible”
(lightweight tags)
Ejemplo: find .git/refs
19. Remotes
● No hay servidor central
● Se pueden agregar varios remotes, copias
externas del repositorio (URL)
● El famoso origin :)
20. 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
21. 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>
22. 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 :)
23. Merges
● Fast-forward: git es
inteligente y solo necesita
mover un puntero
● Integrar cambios de una branch en otra
24. 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...
26. 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
27. 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
28. 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.
29. 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
30. git reset
● Se usa a menudo
● Mal usado, puede generar pérdida de
datos (workdir unsafe)
● Tres opciones más usadas:
○ --soft
○ --mixed
○ --hard
31. 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!)
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
● 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.
35. 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 :)
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