git

En esta guia, encontraras las opciones más comunes de uso de git. Tiene el proposito de ser sólo una referencia rápida sin mayor explicación que la mínima necesaria de cada comando.

Configuraciones iniciales de git

Setting up name and e-mail address

git config --global user.name "Your Name"
git config --global user.email "your_email@whatever.com"

Installation Options line endings

git config --global core.autocrlf input
git config --global core.safecrlf true

Create a repository

git init

Add the page to the repository

git add hello.html
git commit -m "First Commit

Check the status of the repository

git status

Adding changes

git add hello.html
git status

git add a.html
git add b.html
git commit -m "Changes for a and b"

git add c.html
git commit -m "Unrelated change to c"
git add 

Note: The current directory (‘.’) will be our file to add. This is the most convenient way to add all the changes to the files of the current directory and its folders. But since it adds everything, it is a good idea to check the status prior to doing an add ., to make sure you don’t add any file that should not be added.

Committing changes

git commit

If you omit the -m flag from the command line, git will pop you into the editor of your choice from the list (in order of priority):

History

git log

One line history

git log --pretty=oneline

Controlling the display of entries

git log --pretty=oneline --max-count=2
git log --pretty=oneline --since='5 minutes ago'
git log --pretty=oneline --until='5 minutes ago'
git log --pretty=oneline --author=<your name>
git log --pretty=oneline --all

Getting fancy

git log --all --pretty=format:"%h %cd %s (%an)" --since='7 days ago'

The ultimate format of the log

git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short

--pretty="..." defines the output format.
%h is the abbreviated hash of the commit
%d commit decorations (e.g. branch heads or tags)
%ad is the commit date
%s is the comment
%an is the name of the author
--graph tells git to display the commit tree in the form of an ASCII graph layout
--date=short keeps the date format short and nice

Other tools

gitk

Common aliases

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.hist 'log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short'
git config --global alias.type 'cat-file -t'
git config --global alias.dump 'cat-file -p'

Add the following to the .gitconfig file in your $HOME directory.

[alias]

co = checkout
ci = commit
st = status
br = branch
hist = log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short
type = cat-file -t
dump = cat-file -p

Type and Dump

git cat-file

Command aliases (optional)

If your shell supports aliases, or shortcuts, you can add aliases on this level, too. I use:

alias gs='git status '
alias ga='git add '
alias gb='git branch '
alias gc='git commit'
alias gd='git diff'
alias go='git checkout '
alias gk='gitk --all&'
alias gx='gitx --all'

alias got='git '
alias get='git '

Getting hashes for the previous versions

git hist

git checkout
cat hello.html

########################################################################
Git tiene tres principales estados donde los archivos pueden residir:

  • Commited.- El directorio de git o repositorio almacena los metadatos y objetos de la DBs
    para tu proyecto. Esta es la parte más importante de git y la cual se copia cuando clonas
    un repositorio de otra computadora.
  • Modified.- Se ha cambiado el archivo pero no se ha hecho commit en la DBs.
  • Staged.-Significa que el archivo se ha marcado como modificado en la versión actual para
    ser enviado en la siguiente "commit snapshot"

El flujo básico de trabajo de git es similar a:

  1. Modificas los archivos en tu directorio local.
  2. Pones en stage los archivos, agregando los snapshots de ellos en la "staging area".
  3. Haces "commit", lo cual toma los archivos que existen en la "staging area" y almacena
    los snapshots permanentemente en tu directorio de git

Si una versión particular de un archivo esta en el directorio de git, se considera
Commited. Si está moficado pero ha sido agregado al "staging area", está "Staged". Y si
este fue cambiado desde la ulyima vez que se le hizo un "checked out" pero no está
"Staged", entonces está "Modified"

Los Archivos de configuración pueden estar en tres lugares distintos.

  • /etc/gitconfig : Contiene valores para todos los usuarios en el sistema y todos sus
    repositorios. Para escribir/leer se debe usar

git config --system

  • ~/.gitconfig Especifico por usuario, para leer/escribir en el se debe usar

git config --global

  • En el directorio de git existe el archivo .git/config o en cualquier repositorio.

Cualquier nivel sobreescribe los valores en el nivel previo

Obtener la ayuda

$ git help
$ git --help
$ man git-

Ver la configuración actual

Todos los valores

$ git config --list

Un valor especifico

$ git config user.name

Configurar tu identidad

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Configurar tu editor

$ git config --global core.editor emacs

por default usa vi or vim que son los del sistema.

Configurar tu herramienta de diff

$ git config --global merge.tool vimdiff

git acepta:

  • kdiff3
  • tkdiff
  • meld
  • xxdiff
  • emerge
  • vimdiff
  • gvimdiff
  • ecmerge
  • opendiff

Color

$ git config --global color.ui true

Git Basics

Obtener un repositorio de git

Inicializar un repositorio en un directorio existente: [master] (Ver más abajo clonar)

$ git init

esto crea un subdirectorio llamado .git y la estructura del repositorio. Pero ningun
archivo del proyecto está siendo rastreado. (directorio vacio)

Si se requiere iniciar controlando archivos existentes (contrario a usar un directorio
vacio) probablemente se quiera iniciar a rastrear ciertos archivos y hacer un
commit inicial. Para ello se puede usar los siguientes commandos.

$ git add *.c
$ git add README
$ git commit -m 'initial project version'

Clonar un repositorio existente

$ git clone [url]

ejemplo:

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

Si se requiere clonar un repositorio en un directorio con un nombre diferente se puede
hacer con:

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

NOTA.- Esto es util cuando se está trabajando con diferentes versiones o con parches de
un sistema.

Git puede usar diferentes protocolos de trasnferencia, como por ejemplo:

  • git://
  • http(s)://
  • user@server:/path.git

Checar el estatus de los archivos

$ git status

Seguir nuevos archivos

$ git add [FILE]

Una vez agregado el seguimiento a un nuevo archivo este aparece como "staged"

Seguir archivos modificados

$ git add [MODIFIED_FILE]

Una vez realizado esto el archivo queda "staged" y está listo para el siguiente commit

Si se olvidó, realizar un cambio es necesario modificar el archivo y volver a ejecutar

$ git add [MODIFIED_FILE]

Ignorar archivos

En el directorio del repositorio maestro existe el archivo .gitignore, el contenido del
mismo es similar a:

*.[oa] # ignora archivos que finalizan en .o [objeto] o .a [archivo]
*~ # ignora todos los archivos que terminan con una tilde (~)
*.pyc # ignora los archivos que finalizan en .pyc
*.zip
*.swp
*.diff
*.log
*.tmp
*.pid
# 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
.gitignore # ignora el archivo .gitignore

La primer linea ignora archivos que finalizan en .o [objeto] o .a [archivo], la segunda
línea ignora todos los archivos que terminan con una tilde (~).

NOTA.- Es buena idea configurarlo de inicio, para evitar accidentalmente anexar archivos en
el commit.

La reglas para los patrones en este archivo son:

  • Lineas en blanco o que inicien con # se ignoran.
  • Los "glob" estandar funcionan (*, [abc], ? o [0-9])
  • Se pueden finalizar patrones con una diagonal (/) para especificar un directorio.
  • Se puede negar un patron si se inicia con un signo de exclamación (!)

Ver los cambios "staged" o "unstaged"

Para ver los cambios que aún no han sido "staged"

$ git diff

Para ver que es lo que está "staged" y será enviado en el siguiente commit

$ git diff --cached

Enviar ("commiting") los cambios

Después de poner los cambios en "staged",
Nota.- si se desea cambiar el editor se debe usar git config --global core.editor [command]

$ git diff --check
$ git commit

El mensaje que aparece es una linea en blanco y el mensaje por default es para recordar que
se está cambiando, para un mejor recordatorio se puede anexar los cambios del diff se
puede usar:

$ git diff --check
$ git commit -v

Si se usa la opcion -m se puede anexar la descripción en la linea de comandos.

$ git diff --check
$ git commit -m "Story 182: Fix benchmarks for speed"

El comando $ git diff --check es para verificar los espacios

Saltandose la Area "Staging"

$ git commit -a -m 'added new benchmarks'

Esto sólo funciona para los archivos que ya estan en seguimiento.

Borrando archivos

Borrar archivos del Area "Staging"

$ rm [file]
$ git status

Después para borrarlo del Area "Staging"

$ git rm [file]
$ git status

La siguiente vez que se hace el commit el archivo desaparecerá y ya no tendrá seguimiento.

Si se requiere forzar el borrado, ya que se modificó y se anexo al indice

$ rm [file]
$ git rm -f [file]
$ git status

NOTA.- Si se requiere trabajar con el archivo pero borrarlo del Area "Staging"

$ git rm --cached [file]

NOTA.- es posible usar patrones, directorios o archivos al comando git rm, ejemplo:

$ git rm log/\*.log

La diagonal invertida antes del *. es necesaria porque git tiene su propia expansión de
nombres de archivos adicionales a la expansión del shell.

Para borrar los archivos que terminan con ~ se debe usar

$ git rm \*~

Moviendo archivos (35/285)

$ git mv file_from file_to

Esto es similar a hacer:

$ mv file_from file_to
$ git rm file_from
$ git add file_to

Viendo la historia de los commits

Para ver todos los logs

$ git log

Para desplegar la información del log pero con la salida del diff despues de cada entrada.

$ git log -p -2

Para abreviar las estadísticas

$ git log --stat

Para cambiar la salida del log existen otras opciones

$ git log --pretty=oneline

las opciones que se pueden usar son:

  • email
  • format:
  • full
  • fuller
  • medium
  • oneline
  • raw
  • short

La más interesante es format, ya que permite especificar que datos desplegar, ejemplo:

$ git log --pretty=format:"%h - %an, %ar : %s"

Los formatos que puede aceptar son:

Option Description of Output
%H Commit hash
%h Abbreviated commit hash
%T Tree hash
%t Abbreviated tree hash
%P Parent hashes
%p Abbreviated parent hashes
%an Author name
%ae Author e-mail
%ad Author date (format respects the --date= option)
%ar Author date, relative
%cn Committer name
%ce Committer email
%cd Committer date
%cr Committer date, relative
%s Subject

Otro comando util para usar ya sea con oneline o format es --graph

$ git log --pretty=oneline --graph
$ git log --pretty=format:"%h %s" --graph

Estas son algunas de las opciones que acepta la opción de logs.

Option Description
-p Show the patch introduced with each commit.
--stat Show statistics for files modified in each commit.
--shortstat Display only the changed/insertions/deletions line from the --stat command.
--name-only Show the list of files modified after the commit information.
--name-status Show the list of files affected with added/modified/deleted information as well.
--abbrev-commit Show only the first few characters of the SHA-1 checksum instead of all 40.
--relative-date Display the date in a relative format (for example, “2 weeks ago”) instead of using the full date format.
--graph Display an ASCII graph of the branch and merge history beside the log output.
--pretty Show commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format).


Para limitar la salida del log, adicional a la opcion de -<n>

$ git log --since=2.weeks

Se puede especificar la fecha de distintas formas como por ejemplo (“2016-01-15”) o una fecha relativa como “2 years 1 day 3 minutes ago”. La opción --author puede filtrar por un autor en especifico y con la opcion --grep busca una cadena en los mensajes de commits Para ambas opciones se puede usar la opción --all-match tambien se le puede pasar un [path] para poder hacer un filtro sobre cierto directorio o nombre de archivo y se separa con doble --.

Las opciones más comunes de filtros son:

Option Description
-(n) Show only the last n commits
--since, --after Limit the commits to those made after the specified date.
--until, --before Limit the commits to those made before the specified date.
--author Only show commits in which the author entry matches the specified string.
--committer Only show commits in which the committer entry matches the specified string.

 

Ejemplo:

$ git log --pretty="%h - %s" --author=knel --since="2014-07-10" --before="2014-07-12" \ --no-merges -- aaddons/

Deshaciendo cosas

Cambiando el último commit

$ git commit --amend

Por ejemplo, si se omitio un archivo en el 'initial commit' se puede hacer lo siguiente:

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

Si se cambiaron dos archivos pero se agregaron usando un git add * y se quería hacer dos cambios en su lugar. Para sacar el archivo del staging area, se puede usar:

$ git reset HEAD [file]

Si se quiere descartar los cambios que se han realizado a un archivo en particular se puede usar:

$ git checkout -- benchmarks.rb

Trabajando con repositorios remotos

Para visualizar los servidores remotos que están configurados con git clone:

$ git remote

Se puede usar la opción -v para ver la URL ligada.

$ git remote -v

De todos los repositorios se puede hacer un pull pero unicamente de aquellos que usen ssh seran a los unicos a los que se les pueda hacer un push.

Agregar repositorios remotos

$ git remote add [shortname] [url]

Esto agrega un repositorio remoto con tal vez el mismo contenido del directorio, pero que puede estar desarrollando otra persona en una rama (branch) diferente. Por eso se usa el shortname, para identificarlo.

Trayendo y jalando de los repositorios remotos.

Por ejemplo, para hacer un pull toda la información que tiene un shortname, pero que no tienes en el repositorio se puede usar. Para despues hacer el merge de la información.

$ git fetch [shortname]
o
$ git fetch [remote-name]

Con esto no se hacen los merges en automático, si se quiere hacer ambas operaciones se usa

$ git pull

Pushing a los repositorios remotos.

$ git push [remote-name] [branch-name]

Ejemplo:

$ git push origin master

Inspeccionar un repositorio remoto

$ git remote show [remote-name]

Remover y renombrar un repositorio remoto

$ git remote rename [shortnameorigin] [shortnamefinal]
$ git remote -v

Para borrar una referencia

$ git remote rm [shortname]
$ git remote -v

Etiquetado

Listar etiquetas

$ git tag

Buscar etiquetas

$ git tag -l 'v1.4.2.*'

Creando etiquetas

Etiquetas Anotadas

$ git tag -a v1.4 -m 'my version 1.4'

o

$ git tag -a v1.4

Para visualizarlas

$ git show v1.4

Firmar etiquetas con GPG, asumiendo que tengas una llave privada.

$ git tag -s v1.5 -m 'my signed 1.5 tag'

Etiquetas ligeras

$ git tag v1.4-lw

Verificar etiquetas, usa GPG y la clave publica

$ git tag -v v1.4.2.1

Etiquetas tardias.

Si se olvidó etiquetar algo se puede usar:

$ git tag -a v1.2 9fceb02

Compartir etiquetas.

por default no se exportan al repositorio

$ git push origin v1.5

Enviar muchas etiquetas al repositorio que no existan ahí.

$ git push origin --tags

Tips and Tricks

Autocompletar

cat /etc/bash_completion.d/git-prompt

Git Aliases

$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.unstage 'reset HEAD --'
$ git config --global alias.visual "!gitk"

Branching

Visualizar las ramas.

$ git branch
$ git branch -v
$ git branch -a

Crear una nueva rama

$ git branch [name]

Cambiarse a una rama existente

$ git checkout [name]

Branching y Merging

Crear una rama y cambiarse al mismo tiempo.

$ git checkout -b iss53

Combinar

$ git merge [name]

Borrar las ramas.

NOTA.- Esto se realiza cuando el master y el hotfix apuntan al mismo punto, y ya no es necesario conservarlos.

$ git branch -d hotfix

O un borrado forzado

$ git branch -D hotfix

Merge básico

$ git checkout master
$ git merge iss53

Si existe un problema lo va a marcar y se puede visualizar con un git status. Se debe editar el archivo y donde se marca el conflicto se debe borrar, las marcas y dejar el código correcto. Posterior se ejecuta un git add [archivo]

Para borrar las ramas es importante ejecutar

$ git branch --merged

NOTA.- La lista presenta el nombre de cada rama seguido de un *, y si no se presenta el signo es una buena señal de que se puede borrar con git branch -d

Para ver aquellas ramas que no se les ha hecho el merged

$ git branch --no-merged

Ejemplo (64-69):

$ git checkout -b iss53
$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
$ git checkout master
$ git checkout -b 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
$ git checkout master
$ git merge hotfix
$ git branch -d hotfix
$ git checkout iss53
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
$ git checkout master
$ git merge iss53
$ git status
$ git mergetool
$ git status
$ git commit
$ git branch -d iss53

$ git checkout develop
$ git branch aeco_point_of_sale_0.0
$ git checkout aeco_point_of_sale_0.0
$ git add .
$ git com -m "[NEW] AECO Point of sales"

#$ git tag -a aeco_point_of_sale_v0.0.0 -m '[aeco_point_of_sale][0.0.0]'
$ git checkout develop
$ git merge --no-ff aeco_point_of_sale_0.0
#$ git tag -a v0.0.0 -m "aeco_point_of_sale" ###No se si antes o después se crea
$ git push origin develop:develop            ###duda si se crea uno nuevo
$ git push origin --tags

Ramas remotas

Actualizar a lo que está en el server.

$ git fetch origin

Pushing

Si se tiene un branch local y se desea que otros trabajen con el.

$ git push [remote] [branch]

Ejemplo:

$ git push origin serverfix

o

$ git push origin serverfix:awesomebranch

Esto es útil si se quiere que la rama en el servidor tenga un nombre diferente

Ramas remotas

Para trabajar con una rama remota creando una rama local

$ git checkout -b serverfix origin/serverfix

Rastreo de ramas remotas

Es útil si sólo se desea hacer un git pull, en lugar de un checkout en especifico, cuando alguien hace un cambio y se desea obtener.

$ git checkout --track origin/serverfix

Para configurar una rama local con un nombre diferente a la remota.

$ git checkout -b sf origin/serverfix

Borrado de ramas remotas.

$ git push [remotename] :[branch]

ejemplo:

$ git push origin :serverfix

Rebasing (cambio de base) [81]

Se recomienda sólo hacerlo local.

$ git checkout experiment
$ git rebase master

$ git rebase --onto master server client

Servidores git

Protocolo Local (Permisos de archivos)

Clonar:

$ git clone /opt/git/project.git
o mejor:
$ git clone file:///opt/git/project.git

Agregar un repositorio local a un projecto de git, como si fuera en red:

$ git remote add local_proj /opt/git/project.git

Protocolo SSH

Clonar:

$ git clone ssh://user@server:project.git
o (se asume se usa ssh)
$ git clone user@server:project.git

Protocolo git (Puerto: 9418, Sin seguridad)

Protocolo HTTP/S

Configurar:

$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update

Clonar:

$ git clone http://example.com/gitproject.git

Configurar Push usando WebDAV

https://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt

Poniendo git en el servidor

Crear un repositorio desnudo

$ git clone --bare my_project my_project.git

Poner el repositorio desnudo en el servidor.

$ scp -r my_project.git user@git.example.com:/opt/git

Clonar el repositorio

$ git clone user@git.example.com:/opt/git/my_project.git

Asignar permisos al servidor

$ ssh user@git.example.com
$ cd /opt/git/my_project.git
$ git init --bare --shared

Configuraciones pequeñas

  • crear un usuario git en el servidor
  • Solicitar a cada usuario que necesite acceso de escritura su llave publica de SSH
  • Agregar cada llave al archivo ~/.ssh/authorized_keys del usuario git.

Otra solución puede ser usando un LDAP centralizado.

Generar la llave publica SSH

$ ssh-keygen
$ mail ~/.ssh/id_rsa.pub

Más información:

http://github.com/guides/providing-your-ssh-key

Configurando el servidor

$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh
$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
$ cd /opt/git
$ mkdir project.git
$ cd project.git
$ git --bare init

Configuración inicial usando un cliente.

#on Johns computer
$ cd myproject
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@gitserver:/opt/git/project.git
$ git push origin master

Clonar el repositorio por otros usuarios.

$ git clone git@gitserver:/opt/git/project.git
$ vim README
$ git commit -am 'fix for the README file'
$ git push origin master

Restringir shell al usuario git

$ sudo vim /etc/passwd

cambiar

~ git:x:1000:1000::/home/git:/bin/sh

a

~ git:x:1000:1000::/home/git:/usr/bin/git-shell

 

Acceso publico

5.2.3 Private Managed Team [135] Importante

Si se quiere sólo poner un commit en el master

$ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf

Si se quiere obtener la última version (esto requiere que se hayan puesto tags)

$ git describe master

5.3.8 Preparing a Release

Crear la version

$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz

o si se quiere un zip

$ git archive master --prefix='project/' --format=zip > `git describe master`.zip

$ git show HEAD@{2}
$ git show master@{yesterday}

with master..experiment — that means “all commits reachable by experiment that aren’t reachable by master

$ git log master..experiment

The last major range-selection syntax is the triple-dot syntax, which specifies all the commits that are reachable by either of two references but not by both of them.

$ git log master...experiment

Staging interactive

$ git add -i

STASHING

Para trabajar en algo y regresar al estado original sin necesidad de hacer commit se puede usar

$ git stash

listar

$ git stash list

Regresar al stash

$ git stash apply

Borrar

$ git stash drop stash@{0}

Crear una rama de un stash

$ git stash branch testchanges

Reescribiendo la historia

Cambiar el último commit (después de agregar archivos o sólo texto)

$ git commit --amend

NOTA.- No usar si ya se ha hecho un push. (mismo caso que el rebase)

Cambiar multiples mensajes de commit

$ git rebase -i HEAD~3
$ git log --pretty=format:"%h %s" HEAD~3..HEAD

Cambiar un e-mail globalmente.

$ git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
    then
        GIT_AUTHOR_NAME="Scott Chacon";
        GIT_AUTHOR_EMAIL="schacon@example.com";
        git commit-tree "$@";
    else
        git commit-tree "$@";
    fi' HEAD

Debugging


$ git blame -L 12,22 simplegit.rb

$ git blame -C -L 141,153 GITPackUpload.m

$ git bisect start
$ git bisect bad
$ git bisect good v1.0

Submodulos.

Agregar un submodulo externo

$ git submodule add git://github.com/chneukirchen/rack.git rack

Clonar un proyecto con submodulos

$ git clone git://github.com/schacon/myproject.git
$ git submodule init
$ git submodule update
$ git diff
$ git submodule update

fetch
checkout con rama
modificacion
merge
local
push
merge remoto

Referencias:

  1. Git How-to
  2. He olvidado de donde saqué la mayoria de los ejemplos, pero si algún dia las localizo o si alguien encuentra la referencias favor de avisar para darle el crédito a quien corresponda.