Git¶
Enlaces¶
- Libro Pro Git en español
- Cheat Sheat
- git - la guía sencilla :exclamation:
- Git Tutorials & Training by Atlassian :exclamation:
- Detached HEAD en Git
- Github git tutorial
- La Parábola de Git @ CAPSiDE HQ
- Lleva Git al próximo nivel con Git Flow
- git-flow cheatsheet
- Github Release Stats
Comandos básicos¶
Config:
$ git config --global user.name "Eduardo Moreno"
$ git config --global user.email user@dominio.com
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global core.editor "subl -w"
Alternativamente se pueden hacer todos los cambios simultáneamente editando el fichero ~/.gitconfig
. Una configuración podría ser:
[user]
name = Eduardo Moreno
email = user@dominio.com
[alias]
co = checkout
ci = commit
st = status
[core]
editor = subl -w
Creación repositorio (local; crea el subdirectorio .git
):
$ cd first_app
$ git init
Add (fuente):
# stages All
$ git add -A
# stages new and modified, without deleted
$ git add .
# stages modified and deleted, without new
$ git add -u
Commit:
$ git commit
Commit general de cambios:
$ git commit -a
Status:
$ git status
Restituir ficheros borrados:
$ git checkout -f
Log:
$ git log
Log indicando los ficheros modificados:
$ git log --name-status
$ git log --stat
Ficheros modificados en un branch:
$ git diff --name-status master..sip-economy
$ git diff --stat master..sip-economy
Log indicando los commits que afectan a un fichero (fuente):
$ git log --follow filename
Localizar el commit inicial de la rama branch_name
surgida de master
(fuente):
$ git log master..branch_name --oneline | tail -1
Rename:
$ git mv fichero.txt fichero.log
Preparar un servidor:
$ cd first_app/..
$ git clone --bare first_app first_app.git
$ scp -r first_app.git usuario@dominio.com:git
Conectar la copia de trabajo con un servidor:
$ cd first_app
$ git remote add origin usuario@dominio.com:git/first_app.git
(origin
es el nombre de la conexión; puede ser cualquier cosa, aunque si se pone otra cosa habrá que especificar el nombre al hacer push
, ya que origin
es el nombre de destino predeterminado)
Mostrar la lista de conexiones de la copia de trabajo con servidores:
$ git remote -v
Desconectar la copia de trabajo con un servidor:
$ git remote rm origin
(origin
es el nombre de la conexión; puede ser cualquier otro)
Checkout (remoto):
$ git clone usuario@dominio.com:git/first_app.git
Sincronizar con el servidor remoto:
$ git push [origin master]
Info (parecido a svn info):
$ cat .git/config
Crear un tag
$ git tag -a tag_id -m "Creación de tag tag_id."
$ git push --follow-tags
Eliminación de un tag
$ git tag -d tag_id
$ git push origin :refs/tags/tag_id
Eliminación de último commit (fuente)
$ git reset --hard HEAD~1
Si el commit ya ha subido al repositorio hacer además:
$ git push origin HEAD --force
Para olvidar cambios (incluso commits) hechos en local (fuente):
$ git reset --hard origin/master
Diff's¶
Distintos tipos de diff's:
- working vs staging:
git diff
- staging vs snapshot:
git diff --staged
- working vs snapshot:
git diff HEAD
- snapshot vs snapshot:
git diff <from_SHA1> <to_SHA1>
Ficheros modificados entre dos commits:
$ git diff --name-status SHA1 SHA2
$ #o
$ git diff --name-only SHA1 SHA2
$ #o
$ git diff --stat SHA1 SHA2
Diferencias en un fichero entre dos commits:
$ git diff SHA1 SHA2 FICHERO
Muestra la versión de un fichero en un determinado commit:
$ git show SHA:FILE
Branches¶
Creación:
$ git checkout -b alta-usuarios
Listado de branches:
$ git branch
Listado de branches locales y remotos:
$ git branch -a
Seleccionar un branch:
$ git checkout alta-usuarios
Sincronizar con el servidor remoto:
$ git push origin alta-usuarios
Seleccionar trunk:
$ git checkout master
Merge:
$ git checkout master
$ git merge alta-usuarios
$ git branch -d alta-usuarios
Abandonar y borrar un branch local:
$ git checkout master
$ git branch -D alta-usuarios
Borrar un branch remoto. Si después de hacer lo anterior hacemos un git pull la rama local volverá a crearse, ya que seguía estando en el servidor. Esto podemos arreglarlo de la siguiente manera:
$ git push origin :alta-usuarios #suponiendo que la rama en el servidor se llama igual que nuestra ex-rama local
o
$ git push origin --delete alta-usuarios
Seleccionar un branch remoto (fuente):
$ git checkout -b fix#3413 origin/fix#3413
Stash¶
Borrado de la lista:
$ git stash clear
Guardar y recuperar con nombre (fuente):
# Guardar
git stash save nombre
# Listar
git stash list
stash@{0}: On branch: nombre
# Aplicar
git stash apply stash@{0}
# Borrar
git stash drop stash@{0}
Ver los cambios que contiene un stash (fuente):
# Para ver el contenido del stash más reciente
git stash show -p
# Para ver el contenido de un stash en concreto
git stash show -p stash@{1}
Ignorar cambios de un fichero incluido en el repositorio¶
(Fuente) No se trata de la típica entrada en .gitignore
dado que los ficheros allí listados se supone que ni siquiera forman parte del repositorio. Se trata de tener una versión del fichero en el repositorio pero luego no queremos actualizarlo. Para ello ejecutar:
git update-index --assume-unchanged <file>
Para averiguar los ficheros que estamos ignorando de esta forma:
git ls-files -v | grep '^h'
Y si en algún momento queremos recuperar la detección de cambios en el fichero:
git update-index --no-assume-unchanged <file>
Salir de estado "HEAD detached at"¶
En este estado básicamente es que HEAD deja de apuntar al final de una rama (secuencia de commits) para apuntar a un commit concreto directamente. La forma de salir es o volver a hacer checkout de cualquier branch si no se quieren conservar los cambios hechos tras recuperar ese commit, o bien crear un branch temporal para commitear esos cambios y ya luego si se desea incorporarlos a la rama de la que nos habíamos descolgado.
A continuación se describen las dos opciones:
- Si no nos importa perder los cambios
git checkout <branch>
- Si hay cambios tras hacer el checkout del commit:
git checkout -b temp
git checkout <branch>
git merge temp
En la fuente de estas ideas se describe un procedimiento más elaborado para reapuntar el <branch>
(master
en el ejemplo que ponen) a este nuevo branch temporal.
Cambiar el message del último commit¶
(Fuente) Esto sirve si aún no hemos propagado el commit hacia otros repositorios remotos:
git commit --amend
gitbook¶
La utilidad de línea de comando para compilar los libros a epub
por ejemplo se instala con npm
:
sudo npm install gitbook-cli -g
sudo npm install svgexport -g
Una vez disponible, entraremos en el directorio del repositorio que contenga un gitbook y generaremos un epub:
$ cd git/
$ git clone https://github.com/DjangoGirls/tutorial.git
$ cd tutorial/es/
$ gitbook epub ./ ./tutorial.epub
Borrar último commit¶
Para borrar el último commit cuando aún no lo hemos publicado (push) hacer lo siguiente (fuente):
$ git reset --hard HEAD~1
Con esto conseguimos que el puntero del branch apunte al commit anterior al HEAD actual. Es importante que el commit que vayamos a borrar sólo esté en nuestro repositorio. Si ya ha sido propagado a otros repositorios, será mejor deshacer los cambios mediante otro commit.
Sustituir autor de todos los commits¶
-
Crear un clon bare del repositorio
-
A partir de origen remoto (suponemos que tenemos todas las copias de trabajo en
~/git
):$ cd ~/git $ git clone --bare https://github.com/user/repo.git
-
A partir de origen local:
$ cd ~/git $ git clone --bare repo repo.git
-
-
Nos situamos en el directorio con el repositorio bare que se acaba de crear:
$ cd repo.git
-
Copiar y pegar en la terminal el siguiente script sustituyendo las siguientes variables por lo que corresponda:
OLD_EMAIL
CORRECT_NAME
CORRECT_EMAIL
#!/bin/sh git filter-branch --env-filter ' OLD_EMAIL="your-old-email@example.com" CORRECT_NAME="Your Correct Name" CORRECT_EMAIL="your-correct-email@example.com" if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] then export GIT_COMMITTER_NAME="$CORRECT_NAME" export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" fi if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ] then export GIT_AUTHOR_NAME="$CORRECT_NAME" export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" fi ' --tag-name-filter cat -- --branches --tags
-
Pulsar Enter para ejecutar el script.
- Revisar el log de Git.
-
Sincronizar los cambios al origin:
$ git push --force --tags origin 'refs/heads/*'
-
Borrar el clon temporal:
$ cd .. $ rm -rf repo.git
Submódulos¶
Documentación: Enlace 1, Enlace 2.
Añadir submódulo (el directorio PATH que se pone al final no debe existir):
$ git submodule add SUBMODULE_URL PATH
Clonar un repositorio con submódulos:
$ git clone --recursive REPO_URL # si los submódulos tienen a su vez submódulos
$ git clone --recurse-submodules URL # si no hay submódulos recursivos
Actualizar repositorio y submódulos:
$ git pull --recurse-submodules
Borrar commits en repositorio remoto¶
Es importante recordar que si los cambios ya han sido compartidos, es decir otras personas los han sincronizado, se va a romper el histórico para estas personas. Pero si el repositorio es personal, se puede hacer lo siguiente:
-
Situarnos en el commit que nos interese:
- Para borrar sólo el último:
git reset HEAD^ --hard
- Para borrar varios:
git reset <hash_commit> --hard
- Para borrar sólo el último:
-
Forzar los cambios en el repositorio remoto:
git push origin -f