Workshop

Git...

  • Sistema de controle de versão Distribuído (DSCS).
  • Ferramenta Open Source
  • Desenvolvida por Linus Tovals para o Kernel do Linux (2005). 
  • Foco na velocidade, integridade dos dados

Descentralizado...

.. mas centralizado

Descentralizado...

.. mas centralizado

Entendendo o Git

Os espaços...

Os espaços...

Remote

Local

Os espaços...

Remote

Local

Upstream

Repository

Local

Repository

...

Os espaços...

Remote

Local

Upstream

Repository

Local

Repository

Workspace

...

...

Os espaços...

Remote

Local

Upstream

Repository

Local

Repository

Index

(Staging)

Workspace

...

Os espaços...

Remote

Local

Upstream

Repository

Local

Repository

Index

(Staging)

Workspace

Stash

Os espaços...

Ciclo de vida dos arquivos

Sempre trabalhamos com branches, e criamos marcações, chamadas de tags

Branches!!

git init

Inicia um repositório local git

git add

Adiciona um arquivo na área de staging

git commit

Adiciona os arquivos da área de stagins para o seu repositório local

git status

Mostra a situação atual dos arquivos do seu repositório

$ git status
No ramo feature/nova_feature
Changes not staged for commit:
  (utilize "git add <arquivo>..." para atualizar o que será submetido)
  (utilize "git checkout -- <arquivo>..." para descartar mudanças no diretório de trabalho)

	modificado: teste2.txt

Arquivos não monitorados:
  (utilize "git add <arquivo>..." para incluir o que será submetido)

	.project
	novo_arquivo.txt

nenhuma modificação adicionada à submissão (utilize "git add" e/ou "git commit -a")
$ cat my-project/.gitignore
# Ignore modeulos, demas e vendor
/core
/modules
/themes
/vendor

# Ignora arquivos de configurações
sites/*/settings*.php
sites/*/services*.yml

# Ignora arquivos privados
sites/*/files
sites/*/private

# Ignora todos diretórios, exceto um
/some-dir/*
!/some-dir/dont-ignore-me.txt

.gitignore

Arquivos que devem ficar ocultos do git

$ git log
commit 5e31a9080c7f0a9b0390cd7dd2aa8e59a28a7328
Author: Yves Laroche <yves.laroche@logicnow.com>
Date:   Tue Feb 2 20:02:08 2016 +0000

    My first commit

# Short
$ git log --oneline
5e31a90 My first commit

# Limit number of commits
$ git log -10
$ git log --since=1.week
$ git log --after='2016-01-10'

git log

Histórico dos commits enviados para o repositório

RM e MV

$ git rm my-first-file
rm 'my-first-file'

$ git status
On branch my-new-feature
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    my-first-file
$ git mv my-first-file other-name

$ git status
On branch my-new-feature
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	renamed:    my-first-file -> other-name

Let's Git !!!

> mkdir repo1
> cd repo1
> ls -la
total 8
drwxrwxr-x 2 asp asp 4096 jun  5 13:28 .
drwxrwxr-x 3 asp asp 4096 jun  5 13:28 ..
> git init
Initialized empty Git repository in /home/asp/repositories/repo1/.git/
> ls -la
total 12
drwxrwxr-x 3 asp asp 4096 jun  5 13:28 .
drwxrwxr-x 3 asp asp 4096 jun  5 13:28 ..
drwxrwxr-x 7 asp asp 4096 jun  5 13:28 .git

... e criar um arquivo:

> cat > file.txt
this is a file
^C
> ls -la
total 16
drwxrwxr-x 3 asp asp 4096 jun  5 13:30 .
drwxrwxr-x 3 asp asp 4096 jun  5 13:28 ..
-rw-rw-r-- 1 asp asp   15 jun  5 13:30 file.txt
drwxrwxr-x 7 asp asp 4096 jun  5 13:28 .git

iniciar um repositório local...

> git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	file.txt

nothing added to commit but untracked files present (use "git add" to track)
> 

... indexar o novo arquivo...

> git add file.txt 
> git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   file.txt

> 

...Verificar o status do Repositório...

> git config user.name "Your name here"
> git config user.email "your@email.here"

Antes do primeiro commit...configurar a sua conta

Esta informação é usada para saber qual usuário fez em cada commit

> git commit -m "New file file.txt"
[master (root-commit) d87946f] New file file.txt
 1 file changed, 1 insertion(+)
 create mode 100644 file.txt
> git status
On branch master
nothing to commit, working directory clean
> 

... e ver o histórico do nosso repositório:

> git log
commit d87946fa2d170113dcbda46d4b095a1a30e852ca
Author: acanimal <fabio.nowaki@bcash.com.br>
Date:   Mon Feb 20 13:38:27 2016 +0200

    New file file.txt

... vamos fazer o primeiro commit...

... e com um pouco mais de detalhes:

> git log --decorate=full --name-status
commit d87946fa2d170113dcbda46d4b095a1a30e852ca (HEAD, refs/heads/master)
Author: fabio.nowaki <fabio.nowaki@bcash.com.br>
Date:   Mon Feb 20 13:38:27 2016 +0200

    New file file.txt

A       file.txt

git status, mostra o status da árvore de trabalho

git log, mostra o histórico de mudanças através de logs dos commits

git status VS git log

... criar novo arquivo "other.txt", modificar o existente "file.txt" e verificar o status novamente:

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   file.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	other.txt

no changes added to commit (use "git add" and/or "git commit -a")

... adicionar o novo arquivo "other.txt"  para o índice:

> git add other.txt 
> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   other.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   file.txt

... Indexar e comitar as mudanças no mesmo tempo:

> git commit -am "Added new file other.txt"
[master a709c60] Added new file other.txt
 2 files changed, 2 insertions(+)
 create mode 100644 other.txt
> git status
On branch master
nothing to commit, working directory clean

... ver o histórico:

> git log --decorate=full --name-status
commit a709c60d5c885beeeaf2a7d6fd6f129dbeead216 (HEAD, refs/heads/master)
Author: fabio.nowaki <fabio.nowaki@bcash.com.br>
Date:   Fri Jun 5 15:59:05 2015 +0200

    Added new file other.txt

M       file.txt
A       other.txt

commit d87946fa2d170113dcbda46d4b095a1a30e852ca
Author: fabio.nowaki <fabio.nowaki@bcash.com.br>
Date:   Fri Jun 5 13:38:27 2015 +0200

    New file file.txt

A       file.txt

Resumo

Trabalhando com branches

git branch

Permite criar, listar, renomear e deletar branches

$ git branch
  develop
  feature/nova_feature
* projeto1
  master
$ git branch 'projeto1'

Cria uma nova branch chamada projeto1

Lista as branches locais

git branch

Permite criar, listar, renomear e deletar branches

$ git branch -d projeto2
$ git branch -m projeto1 projeto2

Renomeando a branch projeto1 para projeto2

Removendo a branch projeto2

# Caso já esteja na branch projeto1

$ git branch -m projeto2
# Removendo branch remota

$ git push origin :projeto2

git checkout

Permite alternar entre branches criadas pelo git branch

$ git checkout 'projeto1'

Altera seu diretório de trabalho para a branch

 

  > git branch projeto1

  > git checkout projeto1

 

 

 

  > git checkout -b projeto1

 

 

... é o mesmo que ...

git merge

Permite fazer o merge entre branches

$ git branch master

Alternar para a branch master

$ git merge 'projeto1'

Fazer merge das alterações da branch 'projeto1' para a 'master

Let's Git !!!

Por padrão, quando criamos um repositório, o Git cria uma branch master:

> git branch
* master

Vamos criar uma branch para corrigir um Bug:

> git branch bug01
> git branch
  bug01
* master

Estamos trabalhando na branch master, vamos mudar nossa working branch para a branch bug01 :

> git checkout bug01
Switched to branch 'bug01'
> git branch
* bug01
  master
> cat > file_on_bug01.txt
fix the bug
^C
> git status
On branch bug01
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	file_on_bug01.txt

nothing added to commit but untracked files present (use "git add" to track)

... criar um novo arquivo para resolver o bug...

...adicionar arquivo e comitar:

> git add file_on_bug01.txt 
> git status
On branch bug01
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   file_on_bug01.txt

> git commit -am "Bug fixed"
[bug01 776d7ee] Bug fixed
 1 file changed, 1 insertion(+)
 create mode 100644 file_on_bug01.txt
> git status
On branch bug01
nothing to commit, working directory clean
> git status
On branch bug01
nothing to commit, working directory clean
> ls -l
total 12
-rw-rw-r-- 1 asp asp 12 jun 11 12:08 file_on_bug01.txt
-rw-rw-r-- 1 asp asp 17 jun  5 15:55 file.txt
-rw-rw-r-- 1 asp asp 21 jun  5 15:54 other.txt

...mudar para master e listar os arquivos:

> git checkout master
Switched to branch 'master'
> ls -l
total 8
-rw-rw-r-- 1 asp asp 17 jun  5 15:55 file.txt
-rw-rw-r-- 1 asp asp 21 jun  5 15:54 other.txt

Listar arquivos na branch bug01:

> git merge bug01
Updating a709c60..776d7ee
Fast-forward
 file_on_bug01.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 file_on_bug01.txt

... e listar os arquivos:

> ls -l
total 12
-rw-rw-r-- 1 asp asp 12 jun 11 15:16 file_on_bug01.txt
-rw-rw-r-- 1 asp asp 35 jun 11 13:48 file.txt
-rw-rw-r-- 1 asp asp 21 jun  5 15:54 other.txt

Agora vamos fazer o merge da bug01 para  master 

E deletar a branch bug01 

> git branch -d bug01
Deleted branch bug01 (was 776d7ee).

Vamos criar uma branch bug02  e modificar a primeira linha do arquivo file.txt e comitar a alteração:

> git checkout master
Switched to branch 'master'
> vi file.txt 
> git commit -am "Added new line on file.txt at master"
[master 3c07391] Added new line on file.txt at master
 1 file changed, 1 insertion(+)
> git checkout -b bug02
Switched to a new branch 'bug02'
> git branch
* bug02
  master
>
> vi file.txt
>
> git commit -am "Modified file.txt on bug02"
[bug02 fa2a1b4] Modified file.txt on bug02
 1 file changed, 1 insertion(+)

Vá para a branch master e modifica o file.txt também:

Fácil? Vamos gerar um conflito!!!

Tente mergear a bug02  na master:

> git branch
  bug02
* master
> git merge bug02
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.

> more file.txt 
<<<<<<< HEAD
New line at 'master'
=======
New line here at 'bug02'.
>>>>>>> bug02
this is a file
.

Vamos verificar o git status ?

> git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:      file.txt

no changes added to commit (use "git add" and/or "git commit -a")

Edite file.txt, resolva os conflitos e tente novamente:

> vi file.txt 
> more file.txt 
New line at 'master'
New line here at 'bug02'.
this is a file

> git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:      file.txt
no changes added to commit (use "git add" and/or "git commit -a")

Execute git add para indicar que os conflitos foram resolvidos e comite:

> git add file.txt 
> git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

nothing to commit, working directory clean
> git commit -am "Merge done"
[master cb2da7c] Merge done
> git status
On branch master
nothing to commit, working directory clean

Criar tag

# Mostrar todas as tags
> git tag

# Criar um tag
> git tag -a 0.1.0 -m 'Release 0.1.0 do projeto'

# Checkout de uma tag específica
> git checkout 0.1.0

# Criar branch da tag
> git checkout -b hotfix-0.1.1 0.1.0
Switched to a new branch 'hotfix-0.1.1'

Resumo

Repositórios Remotos

Remoto

  • Repositório de sincronização
  • Necessário para trabalhar de forma colaborativa
  • Nós fazemos push/pull dos dados do repositório remoto para repositório local

Local

Remote (origin)

pull

push

Lembrando os espacos...

Remote

Local

Upstream

Repository

Local

Repository

Index

(Staging)

Workspace

Stash

git clone

Cria uma cópia de um repositório git

$ git clone git@github.com/gilsondev/eventex.git

git push

Envia os commits do seu repositório local para o repostiório remoto

$ git push origin master

git fetch

Importa somente os índices do repositório remoto para seu repositório local

 

Não é executado merge no seu código

$ git fetch origin

git pull

Importa os commits do repositório remoto para seu repositório local e faz o merge no seu diretório de trabalho atual

$ git pull

git pull é o mesmo que:

$ git fetch origin
$ git merge [remote name]/[branch]

git push

Transferir os commits do repositório local para o repositório remoto

$ git push origin master

git remote

Especifica um repositório remoto para seu repositório local

$ git remote add origin https://github.com/gilsondev/eventex.git

Let's Git !!!

Adicionar um repositório remoto para um projeto local:

> git remote add origin https://github.com/gilsondev/eventex.git
> git remote
origin
> git remote -v
origin	https://github.com/gilsondev/eventex.git (fetch)
origin	https://github.com/gilsondev/eventex.git (push)
>
> git push origin master
Username for 'https://github.com/gilsondev/eventex.git': gilsondev
Password for 'https://gilsondev@github.com':
Counting objects: 17, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (17/17), 1.45 KiB | 0 bytes/s, done.
Total 17 (delta 3), reused 0 (delta 0)
To https://github.com/gilsondev/eventex.git
 * [new branch]      master -> master
> 

Push para "origin" da nossa branch "master" :

> git clone https://github.com/gilsondev/eventex.git eventex
Cloning into 'eventex'...
Username for 'https://github.com/gilsondev/eventex.git': gilsondev
Password for 'https://gilsondev@github.com': 
remote: Counting objects: 23, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 23 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (23/23), done.
Checking connectivity... done.

...e veja as nossas branches e as configurações remotas:

> git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/fix01
  remotes/origin/master

> git remote -v
origin	https://github.com/gilsondev/eventex.git (fetch)
origin	https://github.com/gilsondev/eventex.git (push)

Vá para outra pasta e clone o repositório remoto:

git clone...

 

  • Configura uma origin remota
  • Baixa a branch master

 

Crie o arquivo file02.txt, comita e de um push para o repositório remoto:

> vi file02.txt
> git add file02.txt 
> git commit -m "New file 02"
[master d78e486] New file 02
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file02.txt
> git push
Username for 'https://github.com/gilsondev/eventex.git': gilsondev
Password for 'https://gilsondev@github.com':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 337 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/gilsondev/eventex.git
   720262a..d78e486  master -> master

Retorne para a pasta anterior (pasta do repositório inicial), adicione um novo arquivo, comite e tenta dar o push:

> git push origin master
Password for 'https://github.com/gilsondev/eventex.git': 
To https://github.com/gilsondev/eventex.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/gilsondev/eventex.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Repositório remoto foi alterado. Precisamos baixar e mergear com nossa branch local:

> git pull origin master
Password for 'https://github.com/gilsondev/eventex.git': 
From https://github.com/gilsondev/eventex.git
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 file02.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file02.txt

Não há conflitos... Então agora nós podemos fazer push  da nossa branch:

> git push origin master
Password for 'https://github.com/gilsondev/eventex.git': 
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 556 bytes | 0 bytes/s, done.
Total 5 (delta 2), reused 0 (delta 0)
To https://github.com/gilsondev/eventex.git
   d78e486..4c15a4e  master -> master

Criar tag e enviar para o repositório remoto

# Mostrar todas as tags
$ git tag

# Criar um tag
$ git tag -a 0.1.0 -m 'Release 0.1.0 do projeto'

# Tags não são 'pushed' por padrão
$ git push origin 0.1.0

# Push todas tags
$ git push origin --tags

# Checkout de uma tag específica
$ git checkout -b 0.1.0

Problema em produção?

# Criar branch da tag
> git checkout -b hotfix-0.1.1 0.1.0
Switched to a new branch 'hotfix-0.1.1'

Outros comandos

git show

Exibe vários tipos de objetos

(blobs, trees e commits)

$ git show

commit 989f6085f0d72c82e41ab587889abc113998b43f
Author: gilsondev <me@gilsondev.in>
Date:   Mon Nov 21 15:52:38 2016 -0200

    Adaptando para trabalho provisorio

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..cec0292
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM fedora:23
+RUN dnf install -y git python-pip gcc python-devel postgresql-devel redhat-rpm-config
+
+RUN mkdir -p /opt/app/channels-example
+WORKDIR /opt/app
+
+COPY . /opt/app/channels-example
+RUN cd /opt/app/channels-example/ && pip install -r ./requirements.txt
+
+# RUN git clone https://github.com/jacobian/channels-example && \
+#     cd channels-example && \
+#     pip install -r ./requirements.txt
+
+# database needs to be set up before web can start serving requests
+CMD sleep 7 && exec python /opt/app/channels-example/manage.py runserver --noworker -v3 0.0.0.0:8000
# Exibe último commit da branch corrente
$ git show

# Exibe último commit da branch especificada
$ git show branch_test

# Exibe último commit da tag
$ git show 0.1.0

# Exibe conteúdo e diff do commit especificado
$ git show 037d081253ec2a538e95bf305d1185c377cfcaa7

git diff

Exibe diferenças entre commits e o workspace

$ echo "Change here" >> LICENSE

$ git diff

diff --git a/LICENSE b/LICENSE
index 9a5d2fc..56b800f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -25,3 +25,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.
+Change here
# Vendo diferenças de um commit específico
# comparado com os mais recentes
$ git diff e7b4712460c80441a69cce6e7429fb7fdf593526

# Vendo diferenças entre dois commits
$ git diff f0caad94fed6ab... 47c18d6359d20...

git stash

"Empurra" as alterações para um outro workspace

# Alterando arquivo gerenciado pelo GIT
$ echo "Changes here" >> LICENSE

# Vendo o status do repositório
$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE

no changes added to commit (use "git add" and/or "git commit -a")
# Usando stash para "deixar de lado" temporariamente a mudança
$ git stash

Saved working directory and index state WIP on master:
e456f2c Remove functions in post hook
HEAD is now at e456f2c Remove functions in post hook

# Verificando o status do repositório
# git status

On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
# Trazendo de volta a mudança feita no arquivo
$ git stash apply

On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE

no changes added to commit (use "git add" and/or "git commit -a")
# Deixando as mudanças em outro workspace
$ git stash

# Trazendo de volta para o workspace oficial
$ git stash apply

# Listando os "stashes" feitos
$ git stash list

# Exibindo stash específico
$ git stash show stash@{0}

# Remover um item do stash no repositório
$ git stash drop stash@{0}

# Remove todos os "stashes" do repositório
$ git stash clear

git difftool

Exibe alterações na ferramenta de diffs

# Invoca a ferramenta de diff definido no .gitconfig
$ git difftool

# Invoca uma ferramenta específica
$ git difftool -t gvimdiff

git mergetool

Inicia ferramenta para aplicação de merge

# Invoca a ferramenta de diff definido no .gitconfig
$ git mergetool

# Invoca uma ferramenta específica
$ git mergetool -t gvimdiff

git bisect

Encontre o commit problemático

# Listando os commits de um repositório

git_bisect_example (master) $ git log
* fe41160 (HEAD, origin/master, master) Refactoring evaluate
* cff0b74 Adding tie test case
* eda39b0 Refactoring evluator
* 4a35ef0 Player 2 wins
* 63735b1 Refactoring evaluate
* a6a5224 Player 1 wins
* 64432c0 First commit
* 7ace5bc Initial commit

# Iniciando o bisect

$ git bisect start

# Definindo um commit como GOOD

$ git bisect good 7ace5bc

# Definindo o último commit como BAD

$ git bisect bad master

Bisecting: 3 revisions left to test after this (roughly 2 steps)
[63735b13802427f9326b3469a41607849335bce6] Refactoring evaluate
# Informando 3 revisões para serem analisadas

$ git lg
* 63735b1 (HEAD) Refactoring evaluate
* a6a5224 Player 1 wins
* 64432c0 First commit
* 7ace5bc (refs/bisect/good-7ace5bc...) Initial commit

# Encontrando o commit que está sem o bug,
# é só voltar para o master e efetuar
# a correção

$ git bisect reset

git reset e revert

Mudando de idéia

git reset

Desfaz commit e deixa as mudanças (ou não)

# Listando o histórico

$ git log

commit a2711bff8027c446b8333cb443df2752ec2b77ab
Author: gilsondev <me@gilsondev.in>
Date:   Tue Dec 27 23:07:00 2016 -0200

    Insert new changes

commit e456f2ca32ea8d49be180014b4d30db961013eef
Author: gilsondev <me@gilsondev.in>
Date:   Wed Nov 9 00:18:35 2016 -0200

    Remove functions in post hook


# Quero resetar o último commit
# (usando hash do commit anterior)

$ git reset e456f2ca32ea8d49be180014b4d30db961013eef

Unstaged changes after reset:
M       LICENSE
# Veja que não perdeu a alteração do último commit

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE

no changes added to commit (use "git add" and/or "git commit -a")


$ git diff 

diff --git a/LICENSE b/LICENSE
index 9a5d2fc..56b800f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -25,3 +25,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN (...)

+Change here
  • soft: O diretório de trabalho e o snapshot não são alterados.
  • mixed (default): O snapshot é alterado mas o diretório de trabalho não altera
  • hard: Altera tudo para o ponto específico.

Use o reset com responsabilidade!!!

git revert

Desfaz commit gerando novo commit

  • É feito a partir de um novo commit;

  • Mantém o histórico anterior a esse commit;

  • Pode reverter um ou mais commits;

  • Pode ser revertido por outro revert.

# Listando os dois ultimos commits

$ git log -2

commit 5b7ee3f5c0bd2f78febef396416102c1187d7a62
Author: gilsondev <me@gilsondev.in>
Date:   Tue Dec 27 23:21:27 2016 -0200

    New changes

commit e456f2ca32ea8d49be180014b4d30db961013eef
Author: gilsondev <me@gilsondev.in>
Date:   Wed Nov 9 00:18:35 2016 -0200

    Remove functions in post hook


# Revertendo o último commit

$ git revert e456f2ca32ea8d49be180014b4d30db961013eef
# Feito o revert, se não tiver conflito, o GIT vai
# pedir a geração de um novo commit.

# ... commit enviado ...

$ git log

commit a1bc2c097b390dd57bb407a5b1156ea1ac564d7d
Author: gilsondev <me@gilsondev.in>
Date:   Tue Dec 27 23:22:32 2016 -0200

    Revert "Remove functions in post hook"
    
    This reverts commit e456f2ca32ea8d49be180014b4d30db961013eef.

commit 5b7ee3f5c0bd2f78febef396416102c1187d7a62
Author: gilsondev <me@gilsondev.in>
Date:   Tue Dec 27 23:21:27 2016 -0200

    New changes

commit e456f2ca32ea8d49be180014b4d30db961013eef
Author: gilsondev <me@gilsondev.in>
Date:   Wed Nov 9 00:18:35 2016 -0200

    Remove functions in post hook

O revert é mais recomendado

Configurações

.gitconfig

Configuração inicial do Git

.gitconfig

  • Arquivo que armazenará as customizações do seu Git
  • Pode ser alterada várias vezes
    • Editando diretamente
    • Alterando usando o comando git config

.gitconfig

  • Três lugares para armazenar as configurações:
    • /etc/gitconfig: Para todos os usuários do SO
    • ~/.gitconfig: Para o usuário específico
    • .git/config: De um repositório específico
  • Cada nível sobrepõem o valor do nível anterior
    1. .git/config
    2. ~/.gitconfig
    3. /etc/gitconfig

.gitconfig

  • Definindo sua identidade nos commits
$ git config --global user.name "Gilson Filho"
$ git config --global user.email "me@gilsondev.in"
  • Definindo editor padrão para escrita dos commits
# Usuarios Gedit

$ git config --global core.editor gedit

# Usuários Atom Editor

$ git config --global core.editor atom

.gitconfig

  • Ferramenta de diff (merge de arquivos)
$ git config --global merge.tool vimdiff
  • Outros comandos
# Listar todas as configurações

$ git config --list

# Listar determinada configuração

$ git config user.name

git-credential-store

Preguiça de inserir minhas credenciais

$ git config credential.helper store
$ git push http://example.com/repo.git
Username: <type your username>
Password: <type your password>

[several days later]
$ git push http://example.com/repo.git
[your credentials are used automatically]
  • ~/.git-credentials: Credenciais específicos por usuário
  • $HOME/.config/git/credentials: Segundo arquivo específico

Exemplo da estrutura no arquivo .git-credentials

https://user:pass@example.com

Gitflow

O gitflow workflow...

  • Define um modelo de branch 
  • Atribui regras especificas para diferentes branches e define como e quando ela deve ser interagida.

Gitflow branches

  • master
  • develop
  • feature
  • release
  • hotfix

Branch: master

Branch de release e estável, então nós devemos gerar tags  através da master.

Branch: develop

Atua como branch de integração das novas features.

Branch: feature

  • Cada nova feature deve ter uma própria branch
  • Quando o desenvolvimento da feature finalizar, deve ser integrada de volta para a develop
  • Features nunca devem ser desenvolvidas direto na master

Branch: release

Uma vez finalizado o desenvolvimento das features e é planejado um deploy:

  • Criar uma branch release da branch develop
  • Neste ponto deve ser feito o teste de regressão
  • Nenhuma nova feature pode ser adicionado a partir deste ponto. Somente corrigido bug, documentação, etc..

Branch: release

Uma vez pronto para o deploy:

  • Mergear com a master e criar uma tab com o número da versão (Ex. 16.5.0)
  • Mergear de volta para develop, pois algo pode ter sido alterado desde a criação da branch

Branch: hotfix

  • Manutenção ou “hotfix” branches são usadas para corrigir bugs emergenciais em produção
  • A branch deve ser criada da master
  • Após a correção, ela deve ser mergeada de volta para a master e develop (ou uma branch release, se estiver alguma)
  • Criar uma tag da master com o número da versão (ex. 16.4.1)

Workflow

Let's Git !!!

master

# Cria novo repositório
$ git init

# Clonar repositório
$ git clone git@github.com:gilsondev/eventex.git

git

develop

# Iniciar desenvolvimento na branch
$ git checkout -b develop master

git

# Inicializar flow
$ git flow init

git flow

feature

# Cria a branch nova-feature com base na develop
$ git checkout -b feature/nova-feature

# Faz o merge da nova-feature para a develop
$ git checkout develop
$ git merge --no-ff feature/nova-feature

# Deleta a branch nova-feature
$ git branch -d feature/nova-feature

# Envia as alterações da branch develop para o repositório remoto
$ git push origin develop

git

feature

# Cria a branch e faz o checkout dela
$ git flow feature start nova-feature

# Faz o merge para a master/develop, deleta a branch 
# e faz push para o remoto
$ git flow feature finish nova-feature

git flow

release

# Cria a release branch 2.3.0 com base na develop
$ git checkout -b release/2.3.0 develop

# Faz o merge da branch release 2.3.0 para a master
$ git checkout master
$ git merge release/2.3.0

# Gera a tag
$ git tag -a v2.3.0

# Faz o merge da branch release 2.3.0 para a develop
$ git checkout develop
$ git merge release/2.3.0

# Deleta a branch 2.3.0
$ git branch -d release/2.3.0

git

release

# Cria a branch e faz o checkout dela
$ git flow release start 2.3.0

# Faz o merge para a master/develop, deleta a branch 
# e faz push para o remoto
$ git flow release finish 2.3.0

git flow

hotfix

# Cria branch para resolver bug emergencial baseado na master
$ git checkout -b hotfix/2.3.7 master

# Após correção, faz merge da branch hotfix para a master
$ git checkout master
$ git merge --no-ff hotfix/2.3.7

# Gera tag baseado na master
$ git tag -a 2.3.7

# Faz o merge da branch hotfix para a develop
$ git checkout develop
$ git merge --no-ff hotfix/2.3.7

# Deleta a branch hotfix
$ git branch -d hotfix/2.3.7

git

hotfix

# Cria a branch e faz o checkout dela
$ git flow hotfix start 2.3.7

# Faz o merge para a master/develop, deleta a branch, 
# faz push para o remoto, e gera a tag
$ git flow hotfix finish 2.3.7

git flow

Boas práticas

Repositório

  • Evite versionar arquivos específicos do seu computador ou processo de desenvolvimento.

  • Exclua branches locais e remotas após o merge.

  • Trabalhe em uma feature branch.

  • Baixe atualizações dos remotes frequentemente.

    • Prefira git pull --rebase, para evitar merges desnecessários. 

Repositório

  • Nunca mover, copiar e remover "sem avisar o git"

# Mover
git mv <nome do arquivo> <novo arquivo>

# Copiar
git cp <nome do arquivo> <novo arquivo>

# Remover
git rm <nome do arquivo>

Commits

  • Use mensagens em português ¹.

  • Escreva uma boa mensagem de commit ²

    • Formato de exemplo:

Resumo no presente com menos de 50 caracteres.

Escreva mais texto explicativo para documentar as suas mudanças

* Mais informações sobre o commit (até 72 caracteres).
* Mais informações sobre o commit (até 72 caracteres).

http:://project.management-system.com/ticket/123

¹ - Depende do idioma padrão usado no projeto

² - http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html

Commits

  • Evite utilizar git commit -m "".

    • Este comando impede que você escreva mensagens com múltiplas linhas com facilidade. Sem o -m, você escreverá suas mensagens no vi.
    • O vim já ajuda você a escrever bons commits, quebrando o texto na coluna correta.
  • Prefira git commit --verbose

    • Poder ver o diff dos arquivos a serem comitados é uma grande facilidade.

Commits

  • Procure responder as seguintes perguntas na sua mensagem de commit: ¹

    • Por que essa alteração é necessária?
    • Como essa alteração resolve o problema?
    • Quais os efeitos colaterais desta alteração?
  • Crie commits pequenos a atômicos

Fluxo de Trabalho

  1. Atualize seu repositório local ou clone um remoto.

    • atualizando repositório local

git checkout master
git pull --rebase
  • clonando repositório remoto
git clone <git-url>
cd <project-name>

Fluxo de Trabalho

2. Crie uma feature branch local.

git checkout -b <branch-name>

3. Realize um rebase frequentemente para incorporar mudanças.

git fetch origin
git rebase origin/master

Fluxo de Trabalho

4. Adicione suas alterações.

git add --all

5. Escreva uma boa mensagem de commit.

git push origin <branch-name>

6. Compartilhe a sua branch.

Fluxo de Trabalho

7. Após o merge com a branch master (ou outra principal), remova suas branches.

git branch --delete <branch-name>
  • removendo uma branch local
git push origin --delete <branch-name>
  • removendo uma branch remota

Materiais para Estudo

Apresentação

É muita coisa para mostrar

Futuro

Dicas práticas para o GIT

Perguntas?

Email: me@gilsondev.in

Blog: gilsondev.in

Telegram/Github: @gilsondev

Twitter: @gilsonfilho

Made with Slides.com