la he liado parda con el git: como borrar cosas que ya he comiteado

¿ Quien no ha hecho un commit de una cosa que no quería ? seguramente todos hemos comiteado algo que luego nos hemos dado cuenta que no tenía que ir y no lo hemos metido en .gitignore. A veces da un poco igual, depende de lo estrictos que seamos en nuestro equipo o nosotros mismos o bien por que estemos publicando el repositorio de forma pública. Con eliminar el fichero, volver a comitear y pushear… aquí no ha pasado nada :D… pero y si quiero borrar algo que no quiero… ¿ qué hago ?

En mi caso he metido un directorio con una compilacion de node via nodeenv[1] que son unos 200MB que no pintan nada en el repo y que además pesa, el objetivo es eliminar ese contenido de una forma limpia. Para ilustrarlo y que no se me olvide voy a documentar un ejemplo ilustrativo 😉

 

# creamos un repositorio nuevo de git llamado foo
git init project
cd project

# primer commit
echo "Hola mundo" > readme.txt
git add .
git commit -m"add readme file"

# segundo commit, aquí es donde nos colamos metiendo contenido
mkdir pictures
echo "vacaciones" > pictures/readme.txt
git add .
git commit -m"add new feature"

# hacemos como que no nos hemos dado cuenta y seguimos comiteando
echo "Nuevas caracteristicas" > CHANGES
git add . 
git commit -m"add changefile"

En este punto la hemos liado por que se nos ha colado el directorio de vacaciones en el proyecto y hacemos un facepalm, por que hemos metido la carpeta de pictures con cosas de las vacaciones en el proyecto y eso no lo queremos 😀

¿Ahora como solucionamos esta situación?

Lo que necesitamos es conservar el último cambio pero eliminar el directorio pictures del proyecto de forma que no quede almacenado en git. Para ello y siguiendo la documentación de git checkout[2] vamos a hacer lo siguiente:

  • volver al paso 2 dejando los cambios de 3 en el stage area
  • Crear una rama con los cambios de stage
  • mover el head del master al paso 1
  • mergear el master con la nueva rama

Explicamos los pasos:

Necesitamos trabajar con los ficheros de forma que no modifiquemos la rama master y nos creamos una rama para reparar que se llamará ‘fix-mess-up’ y la dejamos en el punto anterior a cuando la hemos liado, es decir hace dos commits.

# creamos una rama en la que trabajar la reparacion
git checkout -b fix-mess-up
# volvemos dos commits atrás y dejamos los cambios en el stage, de forma que podemos manejarlos, quitar, añadir, etc...
git reset --soft HEAD~2
# vemos lo que hay en el stash, pendiente de comitear
git status
# quitamos del stash la carpeta de pictures
git reset HEAD pictures/
# ahora tenemos el directorio pictures que tenemos que eliminarlo o meterlo en .gitignore
rm -fr pictures
# aplicamos los cambios en nuestra rama, esto debería ser el contenido correcto
git commit -m"fixed mess up"

Ahora que ya tenemos una rama buena, vamos a eliminar el contenido no deseado de master y echunfarle nuestra rama con la reparación.

# cambiamos a la rama master
git checkout master
# volvemos dos commits atrás y nos cargamos lo que haya con el hard!
git reset --hard HEAD~2
# mezclamos lo que tenemos en la rama fix-mess-up en el master
git merge fix-mess-up

Y en este momento ya lo tenemos reparado, solo falta borrar la rama de fix-mess-up que ya no la necesitamos.

#borrar la rama de la reparación que ya no es necesaria
git branch -d fix-mess-up

 

Nota:

Para que no se me olvide, en el momento en que se hacen checkouts o resets, se entra en modo deatached, con lo que el puntero de HEAD no está en el último commit y cada modificación que se haga a partir de ahí se mete en un branch virtual. Para no perder estos cambios hay que hacer o bien un branch o un tag tal y como se indica en la documentación de git checkout[2]

It is important to realize that at this point nothing refers to commit f. Eventually commit f (and by extension commit e) will be deleted by the routine Git garbage collection process, unless we create a reference before that happens. If we have not yet moved away from commit f, any of these will create a reference to it:

$ git checkout -b foo   (1)
$ git branch foo        (2)
$ git tag foo           (3)

 

[1] http://ekalinin.github.io/nodeenv/

[2] https://git-scm.com/docs/git-checkout#_detached_head

gnome no levanta después de login con ligthdm

Hoy hemos solucionado un problema que aunque es poco común es recurrente. Hay ocasiones en que al intentar acceder a nuestro equipo usando el login manager como en este caso ligthdm no es posible. Tras introducir la contraseña válida vemos como un flash de cambio de pantalla entre el login manager y lo que debería ser nuestro escritorio y nos devuelve al login manager.

En mi caso, esto me ha ocurrido un par de veces o tres a lo largo del tiempo y lo peor es empezar a buscar logs. El problema es que hay algo que no permite levantar nuestro entorno ya que la password es correcta, así que debe ser algo que ejecuta el servidor X con nuestro usuario o bien algo de gnome , en este caso.

Dejo aquí un checklist de cosas para testear:

  • arrancar en consola tty ( control + alt + f1 ) acceder con tu usuario
  • revisar el contenido del fichero .xsession-errors
  • parar nuestro login manager, por ejemplo ( /etc/init.d/lightdm stop ) y arrancar las X con startx. Comprobar si arranca y si hay errores
  • Revisar que el fichero  ~/.Xauthority tengo como propietario a tu usuario. Puede ocurrir que este fichero tenga como propietario a root y este sería el motivo por el que no arranca tu sesión. Elimínalo e intenta acceder a tu escritorio de nuevo.
  • revisar ficheros de log de sistema del servidor X /var/log/Xorg.0.log
  • revisar ficheros de log de login manager /var/log/lightdm/lightdm.log /var/log/lightdm/lightdm.log

 

En este caso el problema era el fichero .Xauthority que pertenecía a root, borrándolo y levantando las X de nuevo ha funcionado sin problemas.