domingo, 27 de febrero de 2011

Ad-hoc git infrastructure for team development

En este articulo se va a explicar como crear un repositorio "servidor" de git para poder trabajar en equipos de desarrollo distribuidos en varias maquinas, como nota adicional cabe destacar que si lo que se necesita es usar el git para desarrollo en solitario, es tan sencillo como crear un repositorio (git init), y directamente usarlo.

Para ir mas al tema, se puede ver en el grafico se tienen dos roles, uno es un "server" linux (alternativamente existen maneras de utilizar un servidor windows) y el otro la terminal de desarrollo que puede ser de cualquier OS. Se puede crear este setup en 3 simples pasos:

  • Crear un usuario en el servidor (Opcional) y crear el repositorio vacio con permisos de escritura para ese usuario
  • Clonar el repositorio desde otro lugar para hacer el "first commit"
  • Clonar el repositorio desde las terminales
Crear el usuario (Opcional) y el repositorio en el server

root@server# adduser git
(Va a pedir informacion acerca del nuevo usuario como el password que se pedira mas adelante)

El repositorio debe ser creado en un directorio al que el usuario "git" o el que hayan elegido tenga acceso, para eso tienen que cambiar a ese usuario mediante el comando login:

root@server:~# login
El cual les va a pedir usuario y password, posteriormente se debe crear un directorio para el nuevo repositorio y entrar en el

git@server:~# mkdir repositorio
git@server:~# cd repositorio
Y finalmente, crear el repositorio (Prestar especial atencion al parametro --bare que indica que se esta creando un repositorio "central")

git@server:~/repositorio$ git init --bare

Inicializar el repositorio

Para hacer esto hay que clonar el repositorio desde un client (o puede ser en el mismo servidor) y efectuar el primer commit
user@client:~$ git clone git@server:repositorio
remote: Counting objects: 3, done.
Receiving objects: 100% (3/3), 202 bytes, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
user@client:~$ cd repositorio
user@client:~/repositorio$ touch README
user@client:~/repositorio$ git add README
user@client:~/repositorio$ git commit --message 'first commit'
[master (root-commit) 5b4ee6e] first commit
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README
user@client:~/repositorio$ git push origin HEAD:refs/heads/master
Counting objects: 3, done.
Writing objects: 100% (3/3), 203 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@localhost:repositorio
* [new branch] HEAD -> master
Clonar el repositorio desde las terminales

En cada workstation desde donde se va trabajar con el repositorio, se tiene que ejecutar el siguiente comando
user@client:~$ git clone git@server:repositorio
remote: Counting objects: 3, done.
Receiving objects: 100% (3/3), 202 bytes, done.
remote: Total 3 (delta 0), reused 0 (delta 0)

miércoles, 16 de febrero de 2011

git push --force and merging without understanding are both FORBIDDEN

When we make "git push" and the changes are rejected, the two "fast" options are incorrect options:

  • make a "git push --force"
  • do a quickly merge after git pull
Both options lead to different kinds of disasters.

git push --force only "destroy" changes made by the others by overwriting the history with not fast-forward, it's desired the use of git checkout and "overwrite" the tree to revert changes, and KEEP the history. Even the latter must be avoided if possible

Merging without understanding is wrong too, the merge operation must be a pair task with the entire team or almost somebody responsible and with time to dedicate to that task (the author(s) of the commit being merged). Because of this, the developers must work in separated branchs and merge the changes WHEN THEY ARE READY, not as in the example:

Bill: "Tim knows as fix this fu**ing bug , then I will send my changes to the central repository and so that he can fix them..." (git push) "Ooops! rejected push, I need to pull and then merge, BUT QUICKLY, because we need to fix this a continue working. There are diverged changed made by Richard to merge with my changes, but HE WENT TO LUNCH, Then i will merge (and solve confllicts) in a FEW SECONDS, do MY tests and then push "

later, when Richard return from lunch:

Richard: Hello, good lunch, etc... I will continue working in my tasks
...
Richard: WTF!!! $##@|~]]¡±¡±?¡±!!!!!? ##@~}@?]@]@?]±¡¡¡¡ ··# !!!!
main.cpp: In function 'int main()':
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token
main.cpp:3: error: expected primary-expression before '<<' token

Conclusion: Bill and Tim would have to have worked in a centralized and separated branch and waiting for Richard to properly merge the changes to the "master", with the needed time, dedication and the presence of the authors of all the changes involved in the merge, Also using techniques such TDD it's possible to maintain a base to easily test the "integrity" of any version of the project