Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Curso de Git

http://bit.ly/abrilcursogit

https://github.com/abril/git-course

Baseado em http://git-scm.com/book/pt-br

Navege com as setas

Quem sou eu?

Celestino Ferreira Gomes

O que é?

Características Básicas

Estrutura de Controle

Estrutura de Controle

.git
|-- COMMIT_EDITMSG  # última mensagem de commit
|-- HEAD            # referência atual do checkout
|-- config          # arquivo de configuração do repositório
|-- description     # arquivo de descrição do repositório
|-- hooks           # diretório com arquivos de gatilhos
|   |-- ...
|-- index           # mudanças para commit
|-- info
|   |-- exclude     # configuração de arquivos p/ ñ versionamento
|   +-- refs        # lista de branches e suas referências
|-- logs
|   |-- ...         # arquivos de log das mudanças
|-- objects
|   |-- info
|   │   +-- packs   # informações sobre pacotes
|   +-- pack
|       |-- ...     # pacotes e indices
|-- packed-refs
|-- refs
    |-- heads
    +-- tags

Objects Database

Todos os objetos se registram da mesma forma.

conteudo

header + conteudo

"2e6f9b0d5885b6010f9167787445617f553a735f"

zlib(header + conteudo)

.git/objects/2e/6f9b0d5885b6010f9167787445617f553a735f

Objects Database

def put_raw_object(content, type)
  size = content.length.to_s
  LooseStorage.verify_header(type, size)

  header = "#{type} #{size}\0"
  store = header + content

  sha1 = Digest::SHA1.hexdigest(store)
  path = @directory + '/' + sha1[0...2] + '/' + sha1[2..40]

  if !File.exists?(path)
    content = data - scale = 2Zlib::Deflate.deflate(store)

    FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
    File.open(path, 'wb') do |f|
      f.write content
    end
  end
  return sha1
end

Objects Database

type size
data

Objects Database

blobs

  • Rakefile
  • source.rb
  • source_test.rb
  • blob: 2e6f9b
  • blob: 7034fe
  • blob: 8034f1
blob size
file data

2e6f9b0d5885b6010f9167787445617f553a735f

Objects Database

trees

  • /
  • Rakefile
  • /lib
  • source.rb
  • /test
  • source_test.rb
  • tree: 1a2b3c
  • blob: 2e6f9b
  • tree: 2b3c4d
  • blob: 7034fe
  • tree: 5b32ad
  • blob: 8034f1
tree size
040000 tree 1a2b3c... /
100644 blog 2e6f9b... Rakefile
...

ob772ec8eb9ae8952c3c1e56a9ffbe49385cc83a

Objects Database

commits (snapshots)

  •  
  • /
  • Rakefile
  • /lib
  • source.rb
  • /test
  • source_test.rb
  • commit: 3e4c5d
  • tree: 1a2b3c
  • blob: 2e6f9b
  • tree: 2b3c4d
  • blob: 7034fe
  • tree: 5b32ad
  • blob: 8034f1
commit size
tree ob772e...
parent 12cb23...
author Someone <aliress>
commiter Someone <aliress>
commit message
...

7216b02627bc3d6ef57008f7ff67f0f8f13f488e

Objects Database

commits

  •  
  • /
  • Rakefile
  • /lib
  • source.rb
  • /test
  • source_test.rb
  • commit: 3e4c5d
  • tree: 1a2b3c
  • blob: 2e6f9b
  • tree: 2b3c4d
  • blob: 7034fe
  • tree: 5b32ad
  • blob: 8034f1
  • commit: 61db26
  • tree: 1a2b3c
  • blob: 41d300
  • tree: 2b3c4d
  • blob: 7034fe
  • tree: 5b32ad
  • blob: 2a03fb

Objects Database

tags

  •  
  •  
  • /
  • Rakefile
  • /lib
  • source.rb
  • /test
  • source_test.rb
  • tag: 6e7a8b
  • commit: 3e4c5d
  • tree: 1a2b3c
  • blob: 2e6f9b
  • tree: 2b3c4d
  • blob: 7034fe
  • tree: 5b32ad
  • blob: 8034f1
tag size
object 7216b0...
tag tag-name
...

0bc9a42eb66d7ae36bf44af8ff5a3888e8a02d12

Instalação

Acessar o site oficial do Git e fazer o download de acordo com seu sistema operacional.

http://git-scm.com/downloads

Obtendo ajuda

$ git help

usage: git <command> [<args>]

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   ...
   tag        Create, list, delete or verify a tag object signed with GPG

See 'git help <command>' for more information on a specific command.

Configurando

Sintaxe:

$ git config [<options>] [<key> <value>]

  1. Sistema --system: /etc/gitconfig

    $ git config --system
    
  2. Global --global: ~/.gitconfig

    $ git config --global user.name "Celestino Gomes"
    $ git config --global user.email "celestino.gomes@abril.com.br"
    
  3. Repositório --local: ./.git/config Esse somente em um repositório ;)

    $ git config [--local] core.ignorecase true
    
$ git config user.name   # Imprime "Celestino Gomes"
$ git config --list      # Lista as chaves configuradas para o repo atual

O Básico

Criando um repositório local.

  1. git init: Cria um repositório a partir do diretório atual.

  2. git clone: Cria um repositório a partir de um outro repositório já existente.

    $ cd repos
    $ git clone https://github.com/abril/git-course.git
    
    $ cd repos
    $ git clone https://github.com/abril/git-course.git curso-de-git
    

O Básico

Gravando as mudanças no repositório.

Abaixo uma imagem que explica o ciclo de vida dos arquivos em um repositório git.

Ciclo de vida dos arquivos

O Básico

Verificando o estado dos seus arquivos

$ git status
# On branch master
nothing to commit (working directory clean)

$ echo 'conteudo' > README
$ git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#    README
nothing added to commit but untracked files present (use "git add" to track)

O Básico

Preparando suas mudanças para integração

git add <path>

Exemplo:

$ git add README

O Básico

Verificando o estado dos seus arquivos II

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
#   new file:   README
#

O Básico

Ignorando Arquivos

$ cat .gitignore

É comum usar para ignorar arquivos temporários, log e configurações locais.

$ echo '*.log' >> .gitignore

O Básico

Visualizando suas modificações (selecionadas ou não)

git diff [--cached] [[--] <path>]

Exemplo:

$ git diff
diff --git a/README b/README
index 0cfbf08..bcaa3b0 100644
--- a/README
+++ b/README
@@ -1 +1,2 @@
 2
+conteudo

O Básico

Fazendo commit de suas mudanças

git commit [<options>]

$ git commit -m 'meu primeiro commit no git \o/'

Se não passar -m com uma mensagem, o git commit vai abrir o editor padrão configurado para o sistema.

git config --global core.editor vi

O Básico

Removendo arquivos

git rm [-r] <path>

Movendo arquivos

git mv <current_path> <new_path>

Exemplo

$ git mv README LEAIAME

É a mesma coisa que:

$ mv README LEIAME
$ git rm README
$ git add LEIAME

O Básico

Visualizando o Histórico de commits

git log [<options>] [<since>..<until>] [[--] <path>...]

$ git log --oneline --graph

O que tem em um commit?

git show <commit>

O Básico

Modificando seu último commit

git commit --amend

Use apenas em seu repositório local, antes de integrar com outros repos

Tirando um arquivo da área de seleção

$ git reset HEAD

Desfazendo um arquivo modificado

$ git checkout -- arquivo

O Básico

Fluxo completo

$ git init # git clone <repo>
$ git add .
$ git commit -m 'Primeiro commit'

Sugestão de atalhos

git config --global alias.st 'status'
git config --global alias.one 'log --oneline'
git config --global alias.oneg 'log --oneline --graph'
git config --global alias.ci 'commit'
git config --global alias.cim 'commit -m'

Branches

No git, estamos sempre trabalhando em um branch. O nome do branch padrão é o master. Mas o que é um branch no git?

$ git branch
* master

O branch é nada mais que uma referência (ponteiro) móvel para um commit. Logo:

Branch apontando para o histórico de commits

Branches

$ git branch testing vai criar um novo branch, apontando para a referência atual.

Múltiplos branches apontando para o histórico de commits

Branches

Como o git sabe o branch em que você está atualmente? Ele tem um ponteiro especial chamado HEAD.

HEAD apontando para o branch em que você está

Branches

Para mudar de branch, use git checkout <branch-name>

$ git checkout testing

O HEAD aponta para outro branch quando você troca de branches

Branches

Como juntar as coisas? Existem duas estratégia, sendo elas merge ou rebase

Branch Merge

$ git merge <commit>

Git cria automaticamente um novo objeto commit que contém as modificações do merge

Branches

Branch Merge

$ git checkout -b iss53
$ git add .
$ git commit -m 'c3'
$ git add .
$ git commit -m 'c5'
# ------------------
$ git checkout master
$ git add .
$ git commit -m 'c4'
$ git merge iss53

Branches

Branch Rebase git rebase <base> <destino>

Fazendo o rebase em C4 de mudanças feitas em C3


$ git checkout -b experiment
$ git add .
$ git commit -m 'c3'
# ------------------
$ git checkout master
$ git add .
$ git commit -m 'c4'
# ------------------
$ git checkout experiment
$ git rebase master

Branches

Branch Rebase

Então é só fazer a atualização do master para o experiment.

$ git checkout master
$ git merge experiment


Fazendo um fast-forward no branch master

Branches

Sugestão de atalhos

git config --global alias.br 'branch'
git config --global alias.co 'checkout'
git config --global alias.rb 'rebase'
git config --global alias.rbc 'rebase --continue'
git config --global alias.rbs 'rebase --skip'
git config --global alias.rba 'rebase --abort'

Tags

Para listas as tags existes

git tag

Para criar uma nova tag

git tag <tagname> <commit>

Branches Remotos

São referências ao estado de seus branches no seu repositório remoto. Quando se cria um repositório através do comando git clone, nosso repositório fica com uma referência para este repositório remoto, e é identificado pela chave origin.

$ cd ~/curso
$ git clone ~/curso/repo-remoto celestino
$ cd meu-repo
$ git remote -v
origin ~/curso/repo-remoto (fetch)
origin ~/curso/repo-remoto (push)

Branches Remotos

Um comando clone do Git dá a você seu próprio branch master e origin/master faz referência ao branch master original.

Branches Remotos

Para adicionar um repositório remoto ao seu repositório local, use:

git remote add <name> <repositorio>

Exemplo:

$ cd ~/curso
$ mkdir joao ; cd joao
$ git init
$ git remote add celestino ~/meu-repo

Branches Remotos

Atualizando as referências

Antes de integrar com um branch remoto, é muito importante atualizar as referências remotas de nosso repositório.

git fetch <repo>

Branches Remotos

O comando git fetch atualiza suas referências remotas

Branches Remotos

Integrando os branches

Tá, mas como eu integro os branches?

git merge <repo/branch>

Ah, então, seu eu quero atualizar meu master com o remoto...

git merge origin/master ou git rebase origin/master

Branches Remotos

Integrando os branches II

A atualização do seu branch com o remoto pode ser mais fácil. git pull <repo> <branch>

git pull == git fetch origin; git merge origin/master

Tá, mas eu prefiro fazer rebase.

git pull --rebase = git fetch origin; git rebase origin/master

:)

Branches Remotos

Quero trabalhar em um branch remoto, como faz?

git checkout -b <branch-local> <repo>/<branch-remoto>

Exemplo:

$ git checkout -b fix origin/fix
Branch fix set up to track remote branch origin/fix.
Switched to a new branch "fix"
$ git branch
master
* fix

Branches Remotos

Enviando para o servidor

git push <repo> [<branch-origem>:]<branch-destino>

$ git push origin master

Se seu branch está "seguindo (tracking)" um branch remoto...

$ git push

Quando se faz um clone, normalmente seu branch master local está seguindo o origin/master

Branches Remotos

Apagando branches remotos

git push <repo> :<branch-destino>

Sim, é um push, porém o branch-origem é NADA, ele apaga o branch no repositório remoto.

Tags Remotas

Assim como os branches, sempre é necessário atualizar as referências das tags

git fetch --tags

Para enviar uma tag criada no repositório local para o remoto.

git push origin <tagname>

Para enviar todas as tags locais

git push origin --tags

Fazendo Stash

Stash é um "branch local" do git que você pode colocar suas mudanças do seu diretório de trabalho, sem perder, e voltar seu branch para um estado estável. Funciona como uma pilha.

git stash

Listar os stashes disponíveis:

git stash list

Fazendo Stash

Para voltar as mudanças para seu diretório de trabalho.

git stash apply [<stash-index>]

Pode ser que, no momento de voltar seu trabalho do stash, o arquivo original não esteja no mesmo estado do seu conteúdo stashed, então, uma forma de tentar reaplicar as mudanças é adicionando a opção --index

git stash apply --index

Fazendo Stash

Você pode remover um stash sem aplicar.

git stash drop [<stash-index>]

Você pode aplicar e remover um stash ao mesmo tempo.

git stash pop [<stash-index>]

Criar um branch do stash

git stash branch <nome-do-branch>

Ferramentas do Git

Debugando

Pode ser que você precise descobrir quem escreveu aqui no arquivo.

git blame <commit-ref> [-L <linhasouregexp>] <arquivo>

Exemplo:

$ git blame README
$ git blame -L 4,8 README
$ git blame -L 4,+5 README
$ git blame -L '/conteudo/',+5 README
$ git blame v1.0.. -- README

Ferramentas do Git

Debugando II - Pesquisa Binária

Você precisa descobri em que ponto no histórico de commits algum bug foi introduzido

$ git log
$ git checkout <commit-ref>
# verificar se está ok ou não
$ git checkout <commit-ref>
# verificar se está ok ou não
$ git checkout <commit-ref>
# verificar se está ok ou não
...

O_o

Ferramentas do Git

Debugando II - Pesquisa Binária

git bisect start [<bad-commit>] [<good-commit>]

Exemplo:

$ git log --oneline
        817a46d (HEAD, master) atualizando README
        28b3818 usando class com prefixo padrao
        ec466bb passando o numero da pagina atual
==>     6a178b5 colocando link para obter mais comentarios
        1110218 rota para listar comentarios por pagina
        fb240bb paginando comentarios no model
        291b8ef (tag: v0.0.2-7) Merge branch 'master'
        638116b Configurando ambiente
$ git bisect start HEAD v0.0.2-7
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[6a178b5...] colocando link para obter mais comentarios

Ferramentas do Git

Debugando II - Pesquisa Binária

Declarar o estado do commit

git bisect <bad|good>

Voltar ao estado atual do branch

git bisect reset

Automático

git bisect run <script>

Resumão

Basicão

git init  /  git clone <repo_path>
git config
git add <path>
git rm [-r] <path>
git mv <current_path> <new_path>
git commit [-m <commit_message>]

Juntando os branches

git merge <branch>
git rebase <branch>

Sincronizado com remoto

git fetch [<repo>]
git pull [<repo> [<branch>]] # == fetch + merge
git push [<repo> [<local_branch>][[:]<remove_branch>]]

Resumão

Atalhos

git config --global alias.st 'status'
git config --global alias.one 'log --oneline'
git config --global alias.oneg 'log --oneline --graph'
git config --global alias.ci 'commit'
git config --global alias.cim 'commit -m'
git config --global alias.br 'branch'
git config --global alias.co 'checkout'
git config --global alias.rb 'rebase'
git config --global alias.rbc 'rebase --continue'
git config --global alias.rbs 'rebase --skip'
git config --global alias.rba 'rebase --abort'