el git nuestro de cada dia

42
nuestro de cada día Nociones y algo más Alan Descoins Tryolabs, 2014

Upload: alan-descoins

Post on 15-Jul-2015

446 views

Category:

Education


0 download

TRANSCRIPT

nuestro de cada díaNociones y algo más

Alan DescoinsTryolabs, 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 TrinidadUn 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