Home RecentChanges

Git

Este documento ilustra a colaboração de dois alunos, aplf e cvaz, num projecto de iaed alojado num repositório privado em http://bitbucket.org/.

O aplf começa por inicializar o repositório, criar um ficheiro, fazer commit e algumas alterações ao código:

[aplf@darkstar ~]$ mkdir iaed
[aplf@darkstar ~]$ cd iaed/
[aplf@darkstar iaed]$ git init
Initialized empty Git repository in /home/aplf/iaed/.git/
[aplf@darkstar iaed]$ cat > hello.c
#include <stdio.h>

int
main()
{
  printf("Hello!\n");
  return 0;
}
[aplf@darkstar iaed]$ gcc -Wall -ansi -pedantic -o hello hello.c
[aplf@darkstar iaed]$ ./hello
Hello!
[aplf@darkstar iaed]$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   hello
#   hello.c
nothing added to commit but untracked files present (use "git add" to track)
[aplf@darkstar iaed]$ git add hello.c
[aplf@darkstar iaed]$ git commit -m 'Initial commit'
[master (root-commit) a3f8961] Initial commit
 1 file changed, 8 insertions(+)
 create mode 100644 hello.c
[aplf@darkstar iaed]$ sed -i s/Hello/Ola/ hello.c
[aplf@darkstar iaed]$ gcc -Wall -ansi -pedantic -o hello hello.c
[aplf@darkstar iaed]$ ./hello
Ola!
[aplf@darkstar iaed]$ git diff
diff --git a/hello.c b/hello.c
index d9b2c97..c76139a 100644
--- a/hello.c
+++ b/hello.c
@@ -3,6 +3,6 @@
 int
 main()
 {
-  printf("Hello!\n");
+  printf("Ola!\n");
   return 0;
 }
[aplf@darkstar iaed]$ git commit -a -m 'Change hello to ola'
[master d4dec23] Change hello to ola
 1 file changed, 1 insertion(+), 1 deletion(-)
[aplf@darkstar iaed]$ git log
commit d4dec231aae0ed524ba3662d5120d8c8de239920
Author: Alexandre P Francisco <aplf@ist.utl.pt>
Date:   Fri Oct 4 22:29:10 2013 +0100

    Change hello to ola

commit a3f8961bdc753ba5f2c6c44adf4247a522be81aa
Author: Alexandre P Francisco <aplf@ist.utl.pt>
Date:   Fri Oct 4 19:44:00 2013 +0100

    Initial commit
[aplf@darkstar iaed]$

Para colocar este projecto em http://bitbucket.org/ é necessário o aplf:

  1. aceder a http://bitbucket.org/ e criar um account (se ainda não tiver um);
  2. criar um novo repositório para o projecto, neste caso com o nome iaed; Na criação do repositório devem ser escolhidas as opções git, private repository, C como linguagem. Podemos também activar a wiki e o issue tracking se quisermos utilizar essas funcionalidades (isto pode também ser feito a posteriori).

Ao criar um novo account, pode ser útil criar e adicionar um par chave pública chave privada SSH. Para tal:

aplf@darkstar:~$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/aplf/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/aplf/.ssh/id_rsa.
Your public key has been saved in /home/aplf/.ssh/id_rsa.pub.
The key fingerprint is:
0c:30:fa:cf:11:44:9d:38:b4:27:78:73:db:7f:68:c7 aplf@darkstar
The key's randomart image is:
+--[ RSA 2048]----+
|    oo+o .       |
|   . =o.o        |
|  . . B.o        |
|   . . O o       |
|    . . S .      |
|     o .   . o   |
|      o     + E  |
|           . o   |
|                 |
+-----------------+
aplf@darkstar:~$ cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIkcZ2HKldk5YQSJ5KShnajWyh7r0dnsjyNmXlm8NeLJjgu4LC5itK/PqvvOw0FyGVTqedYroWIxUhLjTHfRbych9QjfEJ8uKdORFGFJeaEwDopDOs+Un+a9eUPLUKQwEI0cQXUNt1TLqEdn4Vl3YPcxnsKUY/urZ7SB164ugpOs5MwEHZEB4DV6u2E+h0EhPREvpipTGx3dhonVgeLTqvSnhPSaXQYZH6NphwvmKd9W1WNiC4MS0qXLGK10pLee9ClabPjOmMAWeTsuzgcJeXmlG5TOfxyC2zquN5aiuTQ5GDPhj/xWjqVJQqbOGOz2B8llwWExYWXoDV0TgtVd aplf@darkstar
aplf@darkstar:~$

E editar o profile em http://bitbucket.org/ e adicionar uma nova chave SSH introduzindo o output do comando cat acima.

Uma vez criado e configurado o account em http://bitbucket.org/, o aplf pode associar o projecto ao repositório de iaed:

[aplf@darkstar iaed]$ git remote add origin ssh://git@bitbucket.org/aplf/iaed.git
[aplf@darkstar iaed]$ git push -u origin --all
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 574 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To ssh://git@bitbucket.org/aplf/iaed.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
[aplf@darkstar iaed]$ git push -u origin --tags
Everything up-to-date
[aplf@darkstar iaed]$

Este último comando só é necessário se existirem tags, etiquetas nas versões do código.

Sempre que o aplf (ou outro utilizador com acesso ao repositório) fizer alterações é necessário seguir um conjunto de passos:

[aplf@darkstar iaed]$ echo "# This is my README" >> README.md
[aplf@darkstar iaed]$ git add README.md
[aplf@darkstar iaed]$ git commit -m "First commit. Adding a README."
[master 19101b3] First commit. Adding a README.
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
[aplf@darkstar iaed]$ git push -u origin master
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 318 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git@bitbucket.org/aplf/iaed.git
   d4dec23..19101b3  master -> master
Branch master set up to track remote branch master from origin.
[aplf@darkstar iaed]$

Para partilhar o repositório com outro colega basta aceder a http://bitbucket.org/ e partilhar com outro account (que já tem de existir). Neste caso o account cvaz já existe e o aplf tem apenas de partilhar e dar permissões de escrita a cvaz.

Depois de aceitar o convite, cvaz pode clonar o repositório e realizar todas as operações típicas incluindo pull e push:

ist14152@sigma02:~$ git clone https://cvaz@bitbucket.org/aplf/iaed.git
Cloning into iaed...
Password: 
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
ist14152@sigma02:~$ cd iaed/
ist14152@sigma02:~/iaed$ git log 
commit 19101b32b21940c52e9e0a2c4533c7870fd34d45
Author: Alexandre P Francisco <aplf@ist.utl.pt>
Date:   Fri Oct 4 22:40:29 2013 +0100

    First commit. Adding a README.

commit d4dec231aae0ed524ba3662d5120d8c8de239920
Author: Alexandre P Francisco <aplf@ist.utl.pt>
Date:   Fri Oct 4 22:29:10 2013 +0100

    Change hello to ola

commit a3f8961bdc753ba5f2c6c44adf4247a522be81aa
Author: Alexandre P Francisco <aplf@ist.utl.pt>
Date:   Fri Oct 4 19:44:00 2013 +0100

    Initial commit
ist14152@sigma02:~/iaed$

Os colegas de trabalho podem agora começar a colaborar no projecto, mantendo as versões e registando todas as alterações ao projecto.

Imagine-se que o aplf cria um novo ficheiro, faz commit, e push para publicar as alterações em http://bitbucket.org/:

[aplf@darkstar iaed]$ cat >> README.md 

I have access!

[aplf@darkstar iaed]$ git commit -a -m 'Change README'
[master df5c7ef] Change README
 1 file changed, 3 insertions(+)
[aplf@darkstar iaed]$ git push
/home/aplf/.ssh/config line 4: Unsupported option "GSSAPIAuthentication"
/home/aplf/.ssh/config line 5: Unsupported option "GSSAPIDelegateCredentials"
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 323 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git@bitbucket.org/aplf/iaed.git
   19101b3..df5c7ef  master -> master
[aplf@darkstar iaed]$

Notar que o commit não actualiza o estado em http://bitbucket.org/, é necessário fazer push quando o queremos fazer, o que pode apenas acontecer após várias alterações e commit locais.

Agora cvaz pode realizar a operação pull para actualizar o repositório local com as alterações feitas por aplf:

ist14152@sigma02:~/iaed$ git pull
Password: 
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://bitbucket.org/aplf/iaed
   19101b3..df5c7ef  master     -> origin/master
Updating 19101b3..df5c7ef
Fast-forward
 README.md |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
ist14152@sigma02:~/iaed$ cat >> README.md 

Me too!

ist14152@sigma02:~/iaed$ git commit -a -m 'Add note to README'
[master 1819197] Add note to README
 1 files changed, 3 insertions(+), 0 deletions(-)
ist14152@sigma02:~/iaed$ git push
Password: 
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 336 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://cvaz@bitbucket.org/aplf/iaed.git
   df5c7ef..1819197  master -> master
ist14152@sigma02:~/iaed$

Neste caso, cvaz fez também alterações e os respectivos commit, seguidos da operação push para a actualizar também o repositório em http://bitbucket.org/.

Neste caso aplf volta a actualizar a sua cópia local:

[aplf@darkstar iaed]$ git pull
/home/aplf/.ssh/config line 4: Unsupported option "GSSAPIAuthentication"
/home/aplf/.ssh/config line 5: Unsupported option "GSSAPIDelegateCredentials"
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ssh://bitbucket.org/aplf/iaed
   df5c7ef..1819197  master     -> origin/master
Updating df5c7ef..1819197
Fast-forward
 README.md | 3 +++
 1 file changed, 3 insertions(+)
[aplf@darkstar iaed]$ sed -i s/Ola/Ola\ aplf/ hello.c
[aplf@darkstar iaed]$ gcc -Wall -ansi -pedantic -o hello hello.c 
[aplf@darkstar iaed]$ ./hello 
Ola aplf!
[aplf@darkstar iaed]$ git commit -a -m 'Change hello message'
[master 5ce846e] Change hello message
 1 file changed, 1 insertion(+), 1 deletion(-)
[aplf@darkstar iaed]$ git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 360 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git@bitbucket.org/aplf/iaed.git
   1819197..5ce846e  master -> master
[aplf@darkstar iaed]$

Onde também fez algumas alterações...

E cvaz continua a fazer alterações locais sem fazer pull...

ist14152@sigma02:~/iaed$ sed -i s/Ola/Ola\ cvaz/ hello.c
ist14152@sigma02:~/iaed$ gcc -Wall -ansi -pedantic -o hello hello.c
ist14152@sigma02:~/iaed$ ./hello
Ola cvaz!
ist14152@sigma02:~/iaed$ git commit -a -m 'Personalize hello message'
[master 01e6e37] Personalize hello message
 1 files changed, 1 insertions(+), 1 deletions(-)
ist14152@sigma02:~/iaed$ git push
Password: 
To https://cvaz@bitbucket.org/aplf/iaed.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://cvaz@bitbucket.org/aplf/iaed.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again.  See the
'Note about fast-forwards' section of 'git push --help' for details.
ist14152@sigma02:~/iaed$ git pull
Password: 
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://bitbucket.org/aplf/iaed
   1819197..5ce846e  master     -> origin/master
Auto-merging hello.c
CONFLICT (content): Merge conflict in hello.c
Automatic merge failed; fix conflicts and then commit the result.
ist14152@sigma02:~/iaed$ git mergetool
merge tool candidates: tortoisemerge emerge vimdiff
Merging the files: hello.c

Normal merge conflict for 'hello.c':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (emerge):
ist14152@sigma02:~/iaed$ git commit -a -m "Conflict solved"
[master 531591f] Conflict solved
ist14152@sigma02:~/iaed$ git pull
Password: 
Already up-to-date.
ist14152@sigma02:~/iaed$ git push
Password: 
Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 489 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
To https://cvaz@bitbucket.org/aplf/iaed.git
   5ce846e..531591f  master -> master
ist14152@sigma02:~/iaed$

Neste caso, depois de fazer alterações, ao fazer push, foram detectados conflitos! Para resolver os conflitos é necessário fazer pull e utilizar a mergetool como exemplificado acima, onde podemos escolher a ferramenta para resolver o conflito (que abre o editor de texto respectivo). Alternativamente podemos utilizar um dos seguintes comandos para escolher qual dos ficheiros queremos manter:

ist14152@sigma02:~/iaed$ git checkout --ours hello.c
ist14152@sigma02:~/iaed$ git checkout --theirs hello.c

No primeiro caso resolvemos o conflito escolhendo a nossa versão, no segundo caso escolhemos a versão remota.

O aplf volta agora a fazer pull...

[aplf@darkstar iaed]$ git pull
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From ssh://bitbucket.org/aplf/iaed
   5ce846e..531591f  master     -> origin/master
Updating 5ce846e..531591f
Fast-forward
 hello.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
[aplf@darkstar iaed]$ gcc -Wall -ansi -pedantic -o hello hello.c 
[aplf@darkstar iaed]$ ./hello 
Ola cvaz!
[aplf@darkstar iaed]$

Bom trabalho.