Skip to content
Snippets Groups Projects
Select Git revision
  • devel default protected
  • issue#67
  • master protected
  • issue#56
  • week07
  • week06
  • week05
  • week04
  • week08
  • week03
  • week02
  • week01
12 results

git_tuto.Rmd

Blame
  • title: "Tutorial de Git"
    author: "PET Estatística UFPR"
    output:
      html_document:
        highlight: pygments
        toc: true
        theme: flatly
        keep_md: true
    library(knitr)
    opts_chunk$set(comment=NA)


    Cheat sheets para Git

    O modelo de funcionamento do Git:

    Playlists de tutoriais de Git


    O que é o Git?

    TODO


    Download e instalação

    A primeira coisa a fazer é ter instalado os arquivos necessários para o Git funcionar. Em sistemas Debian e suas variações (Ubuntu, LinuxMint, ...), os pacotes necessários podem ser instalados com comandos que, a partir dos repositórios de cada distribuição, instalam o Git na sua máquina.

    Linux

    Em uma sessão de terminal Linux de distribuições Debian (Ubuntu, Mint), execute o código abaixo.

    ## Adicione o ppa para ter a versão mais recente do Git. Descomente e
    ## rode essas duas linhas de comando para isso.
    ## sudo add-apt-repository ppa:git-core/ppa
    ## sudo apt-get update
    
    sudo apt-get install git git-core git-man git-gui git-doc \
        ssh openssh-server openssh-client
    git --version
    
    ## Ferramentas complementares.
    sudo apt-get install gitk meld

    Usuários de Linux baseados no Arch instalam de uam forma ligeiramente diferente.

    pacman -S git openssh meld
    git --version

    O ssh e openssh-* são necessários para a comunicação entre sua máquina e o servidor do GitHub ou GitLab. Iremos configurar repositórios remotos em uma outra sessão. O Git também pode ser instalado em ou sistemas operacionais. Visite Installing-Git e siga as instruções. Os arquivos de instalação podem ser baixados do endereço http://git-scm.com.

    Windows

    Usuários Windows devem visitar https://git-for-windows.github.io/, baixar e instalar. Essa instalação do Git traz o Git BASH que é como um terminal do (Li|U)nix, a Git GUI que é uma interface para trabalhar com Git e Shell Integration que são ações disponíveis no menu aberto pelo botão direto mouse. Além disso, segundo o que consta é que essa instalação tras também a Gitk, uma interface para navegação no histórico.

    Meld é um assistente de comparação de arquivos (file diff). Ele é muito útil como ferramenta para resolver conflitos de merge (mergetool). No entanto, não é obrigatório ter.


    Configurando perfil

    Estas configurações precisam ser feitas apenas uma vez, e servem para determinar algumas opções globais do Git.

    Os comandos abaixo vão configurar o nome de usuário e email. Fique tranquilo que o Git não vai te enviar email, isso é apenas informação que ficará associada ao trabalho que você desenvolver de modo a permitir que os colaborados/gestores do projeto identifiquem suas contribuições e possam entrar em contato, se necessário (principalmente se você fizer aqui de errado). Mesmo que você nunca venha a trabalhar em equipe, apenas localmente, é importante fornecer nome e email. Se trabalhar de duas máquinas diferentes, você pode indentificar no nome de usuário.

    ## Configurações do Git do Batman.
    git config --global user.name "Knight Rider"
    git config --global user.email "batman@justiceleague.org"
    
    ## Configurações do Git do Superman.
    git config --global user.name "Kal-El"
    git config --global user.email "superman@justiceleague.org"

    O --global dessa instrução significa que o que for definido vai valer para todo projeto Git da máquina. É possível fazer definições para cada projeto, ou seja, não globais. Portanto, você pode trabalhar com nomes ou emails diferentes para cada projeto. É possível também criar alias para algumas intruções Git. Embora elas não sejam tão longas, no uso contínuo pode valer a pena. Visite:

    Além disso podemos definir um editor de texto padrão para escrever as mensagens de commits. Por padrão, esse editor é o $EDITOR do seu shell. (Essa etapa pode ser pulada a princípio, como veremos mais pra frente). Esse editor não precisa ser necessariamente o mesmo editor que você usa para escrever [texto, código]. No meu caso uso o Emacs, mas para essa tarefa prefiro o vim por ser um editor embutido, e que não vai carregar uma interface gráfica desnecessariamente quando for preciso escrever uma mensagem de commit. Portanto, aqui pode-se deixar espaço para o vim.

    git config --global core.editor vim

    O Emacs também pode ser carregado embutido no terminal (sem usar o X), usando a opção emacs -nw (de no window) na sua inicialização.

    No Linux, as informações acima passadas ficam salvas em um arquivo na home do usuário chamado .gitconfig. Quando não se usa o --global, as definições ficam salvas dentro do próprio do projeto. Eis o conteúdo do arquivo de configuração do Batman.

    less ~/.gitconfig
    [user]
        name = Knight Rider
        email = batman@justiceleague.org
    [merge]
        tool = meld

    No caso dele, além de nome e email, tem que o meld que é a ferramenta de merge definida como padrão. Para conseguir isso você precisa definir como fez com os demais (how-to-set-meld-as-git-mergetool).

    git config --global merge.tool meld

    Avançado: Para usuários Linux que apreciam o nível de customização que o Linux oferece (como o Batman e nós), é possível configurar o prompt do terminal para mostrar a informação do ramo, usuário, etc. Essa informação estampada facilita um bocado, principalmente em projetos grandes. Visite:


    Criar um projeto versionado

    Instruções do Git

    Já temos o Git devidamente e com credenciais (nome e email) e configurações aplicadas. Vamos então ver como o sistema de controle de versão acontece.

    Todas as instruções do Git são sinalizadas por começar com git seguido da instrução/comando e seus argumentos complementares, se existirem/necessários.

    cd meu1repo
    
    ## Padrão de instruções Git.
    git <instrução> <complementos ...>

    Os comandos abaixo revelam tudo o Git tem, embora dizer o que ele tem não signifique nada diante do que ele pode fazer com o que tem.

    cd meu1repo
    
    ## Ajuda resumida do Git, principais comandos com descrição.
    git help -a
    cd meu1repo
    
    ## Lista de todos os comandos disponíveis.
    git help -a

    Criar um diretório para o projeto Git

    Vamos criar um diretório vazio para começarmos um projeto. Também se pode começar de um diretório que já tenha arquivos e subdiretórios. Você pode fazer isso com seu file manager padrão que no Ubuntu é o Nautilus, no Mint é o Nemo.

    NOTA: o desenvolvimento do Nemo é feito com Git e está disponível no GitHub: linuxmint/nemo.

    Nesse tutorial, as instruções serão todas feitas no terminal mesmo que existam alternativas gráficas para as mesmas. Isso enfatiza no que está sendo feito além do fato de que no terminal todos devem ter os mesmos recursos e os comandos irão produzir os mesmos resultados, o que faz esse tutorial algo reproduzível. Se você considera que uma ferramenta gráfica é mais confortável ou produtiva, sinta-se à vontade para aprendê-la e usá-la.

    if [ -d meu1repo ]
    then
        echo "Diretório existe. Então apagar pasta .git"
        cd meu1repo
        ls -a
        if [ -d .git ]
        then
            echo "Já existe projeto git aqui. Apagar."
            rm -rf .git/
            rm -rf *
        fi
    else
        echo "Diretório não existe."
        mkdir meu1repo
    fi
    
    ## Tudo limpo tal como precisamos.
    pwd
    ls -a
    ## Cria diretório (make directory).
    mkdir meu1repo
    
    ## Entra no diretório (change directory).
    cd meu1repo

    Antes de iniciarmos o repositório, vamos só verificar o cadastro. Se você já usa o Git ou fez os procedimento apresentados na primeira sessão, o comando abaixo vai retornar o nome e email usados e alguns definições adicionais, caso existam. Em caso de ainda não ter configurado o seu Git, informe o nome e email conforme apresentado na sessão anterior.

    ## Mostra as informações/definições do usuário.
    git config --list
    user.name=Knight Rider
    user.email=batman@justiceleague.org
    merge.tool=meld

    Temos um diretório destinado ao projeto que será mantido sobre versionamento, então vamos iniciar um repositório Git nele.

    cd meu1repo
    
    ## Inicia um repositório sob versionamento Git.
    git init

    O Git retorna a mensagem de inicilização do repositório. Nesse momento ele cria um diretório oculto .git/ com subdiretórios que são o coração do sistema de versionamento. Você não deve modificar nada nesse diretório. É por essa razão que ele é oculto. Alterar o conteúdo pode prejudicar ou interromper o funcionamento do Git. Se você quiser encerrar o processo de versionamento fazendo com que esse diretório seja como qualquer outro diretório, é só excluir a diretório .git/. Cada subdiretório do .git/ tem um propósito mas deixaremos os esclarecimentos para o futuro. Por agora vamos apenas conferir a sua estrutura.

    cd meu1repo
    
    ## Mostra todo conteúdo do diretório.
    tree -a

    NOTA: o tree é um programa instalado a parte (third party software) que retorna arte ASCII representado a estrutura de diretórios. Se você usa distribuição Debian, instale com sudo apt-get install tree. Windows: tree.

    Vamos começar da maneira mais simples: criando um arquivo com uma linha de texto apenas. Bem, vale avisar que ao longo desse tutorial, os arquivos serão sempre bem pequenos e dificilmente realistas, mas como o enfoque está no funcionamento, não haverá prejuízo.

    Vamos criar o arquivo com conteúdo também pelo terminal. Se você preferir, abra eu editor de texto favorito (Emacs, Gedit, Geany, RStudio, etc) e faça algo mais criativo.

    cd meu1repo
    
    ## Cria um arquivo com uma linha de conteúdo.
    echo "Meu primeiro repositório Git" > README.txt
    
    ## Lista os arquivos do diretório.
    tree

    O Git está "atento" a tudo que acontece nesse diretório. Ao criarmos o arquivo e pedirmos a situação (status), ele indica que existe um arquivo não restreado (untracked) no diretório. Inclusive sugere uma ação que seria adicionar o aquivo (add). Se o seu sistema operacional está em português, parte dos outputs do Git podem estar traduzidos.

    cd meu1repo
    
    ## Reconhecimento do Git sobre aquivo criado.
    git status

    Para que o arquivo seja incluído no monitoramento é necessário que ele receba o primeiro comando add. Isso marca a entrada dele no projeto como um arquivo que a partir de então será versionado. O status agora não indica mais que ele está untracked mas sim que existem mudanças para serem registradas (changes to be commited). A melhor tradução de commit, pensando no seu uso em Git, é fechar sob segurança. Quando um commit é feito, cria-se um instante na linha do tempo que salva o estado do projeto. Para esse instante o projeto pode ser retrocedido, voltando o condição/conteúdo de todos os arquivos para o momento no qual o mencionado commit foi feito. Você pode voltar para um commit de semanas e até anos atrás.

    O controle de versão não é apenas voltar os arquivos para o conteúdo que eles tinham no passado. Arquivos rastreados que foram deletados ou renomeados são recuperados. Até mesmo as permissões de leitura/escrita/execussão dos arquivos são comtempladas no versionamento.

    cd meu1repo
    
    ## O primeiro `add` submete o arquivo ao versionamento.
    git add README.txt
    git status

    O arquivo README.txt já é visto pelo Git como um arquivo com o qual ele deve se "preocupar", pois está sob versionamento. Vamos agora fazer um registro definitivo sobre o estado desse arquivo (commit). É de fundamental importância que a mensagem de notificação, ou mensagem de commit, reflita as moficações feitas. São as mensagens que serão consultadas quando você precisar desfazer/voltar. Ela deve ser curta (<= 72 caracteres) e ao mesmo tempo informativa. A minha primeira mensagem não será, todavia.

    cd meu1repo
    
    ## Registro de versão.
    git commit -m "Cria arquivo com título."

    NOTA: Sobre mensagens de commit e trabalho colaborativo em Git existem algumas boas práticas que devem ser seguidas. Visite: Git contributing guide.

    O retorno da instrução de commit indica o número de arquivos incluídos no commit e o número de inserções e deleções de linhas. O mais importante está na primeira linha que informa o ramo de trabalho atual (branch) e o sha1 do commit. O sha1 é uma sequência hexadecimal de 40 digitos que representa unicamente o commit, então são 16^40 possibilidades!. É por meio do sha1 que podemos retroceder o projeto. São mostrados apenas os 7 primeiros digitos porque são suficientes para diferenciar commits dentro até mesmo de projetos moderados ou grandes. Visite: sha1-size.

    Vamos criar mais arquivos e acrescentar conteúdo ao já rastreado pelo Git para percebermos o funcionamento. Escrever uma lista de razões para usar o Linux. Deixei a lista curta poder ampliar no futuro e com erros de português para corrigir depois.

    cd meu1repo
    
    ## Adiciona mais linhas ao README.txt
    echo "
    A filosofia do Linux é 'Ria na face do perigo'.
    Ôpa. Errado. 'Faça você mesmo'. É, é essa.
                                -- Lunus Torvalds" >> README.txt
    
    ## Cria uma lista de pontos sobre o porquê de usar o Linux.
    echo "Por que usar o Linux?
    
    * É livre
    * É seguro
    * É customizavel" > porqueLinux.txt
    cd meu1repo
    
    ## Mostra o conteúdo do arquivo.
    less README.txt
    cd meu1repo
    
    ## Mostra o conteúdo do arquivo.
    less porqueLinux.txt

    E o que o Git "acha" de tudo isso? O comando status é o mais usado do Git, principalmente nas etapas de aprendizado. Uma característica diferente do Git, se comparado a outras aplicações de uso por terminal, é que ele é realmente camarada. Nas mensagens de output, o Gitque informa o que aconteceu e também dá sugestões do que fazer.

    cd meu1repo
    
    git status

    O Git retornou dois campos. No primeiro ele diz que existem mudanças no README.txt não encaminhadas para receber registro (not staged for commit) e no segundo ele aponta que o porqueLinux.txt é um arquivo não rastreado (fora de monitoramento).

    Vamos explorar um pouco mais os recursos do Git antes de adicionar as recentes mudanças. Até o momento, temos apenas um commit feito. Para acessar o histórico de registros usamos git log. O histórico mostra o sha1, o autor, data e mensagem de commit. Uma saída mais enxuta é obtida com git log --oneline, útil quando o histórico é longo. É possível fazer restrição no git log, como mostrar os commits a partir de certa data, certo intervalo de datas, para um único autor ou único arquivo. Visite: git-log.

    cd meu1repo
    
    ## Mostra o histórico de commits.
    git log

    O comando diff mostra as diferenças no conteúdo dos arquivos/diretório. No caso, apenas o README.txt está sendo rastreado, por isso o output indica a adição (+) de novas linhas. Na saída tem-se os sha1 das versões comparadas e o intervalo de linhas envolvido na porção modificada (@@). Visite: git-diffs.

    cd meu1repo
    
    ## Diferença nos arquivos versionados.
    git diff

    Vamos aplicar o primeiro add ao porqueLinux.txt para que ele começe a ser versionado. Perceba que ao adicioná-lo, as mudanças, no caso a criação do arquivo com contúdo, já são separadas para receber registro (changes to be commited).

    cd meu1repo
    
    ## Adiciona o arquivo ao processo de reastreamento.
    git add porqueLinux.txt
    git status
    cd meu1repo
    
    ## Mensagem que registra as modificações adicionadas.
    git commit -m "Lista de inicial de o porquê usar o Linux."
    cd meu1repo
    
    git status

    Ainda resta o REAMDE.txt para receber registro. Você não precisa fazer agora. Pode continuar editanto caso não tenha atingido uma quantidade de modificação merecedora de commit. Lembre-se que registros geram conteúdo no diretório .git. Quanto mais commits, mais conteúdo gerado. Mas também, toda vez que você faz um commit, você define um ponto de retorno, um estado salvo, caso precise no futuro recuperar/visitar. O que é uma unidade de modificação comitável você irá definir aos poucos com a prática.

    cd meu1repo
    
    ## Encaminha o arquivo para receber registro.
    git add README.txt
    git status
    cd meu1repo
    
    ## Atribui mensagem de notificação.
    git commit -m "Adiciona frase do Linux Torvalds."

    Agora temos 3 commits e o log apresenta os sha1 e as mensagens correspondentes aos mesmos. Com --oneline resumimos o output mostrando apenas o sha1 e a mensagem de commit.

    cd meu1repo
    
    git log --oneline

    Por meio dos sha1, podemos aplicar o diff para visitarmos as modificações entre dois commits, não necessariamente consecutivos, por exemplo. Também podemos retroceder (checkout, reset, revert) o projeto para alguns desses pontos.

    Abaixo instruímos o Git mostrar as diferenças para um commit atrás. A cabeça (HEAD) é o que se entende como estado mais recente. Usa-se o termo HEAD (cabeça) pois considera-se um crescimento do histórico debaixo para cima no qual um novo commit é colocado em cima dos demais (empilhado). O HEAD@{0} ou apenas HEAD representa o último registro feito. Não é necessário escrever o último HEAD na intrução abaixo.

    cd meu1repo
    
    git diff HEAD@{1}

    Agora inspecionado uma distância de 2 commits a partir do último. Aqui tem-se os dois arquivos envolvidos nesse intervalo de 2 commits. Com --name-only retorna-se só o nome dos arquivos.

    cd meu1repo
    
    git diff HEAD@{2} HEAD@{0}
    cd meu1repo
    
    git diff --name-only HEAD@{2} HEAD@{0}

    Vamos resolver logo o caso da palavra sem acento em porqueLinux.txt. Você abre o arquivo no seu editor de texto e modifica conforme necessário. A modificação compreende um linha apenas mas aí lembrei de mais coisas e acrescentei. O git diff mostra as diferenças. Epa! As diferenças não eram entre commits? O conteúdo adicionado ainda não recebeu notificação!

    cd meu1repo
    
    echo "Por que usar o Linux?
    
    * É livre
    * É seguro
    * É customizável
    * Tem repositórios de software
    * Atualização constante
    * Desempenho" > porqueLinux.txt
    cd meu1repo
    
    ## Depois de corrigir palavras e adicionar conteúdo.
    git status

    O Git sugere você aplicar add para preparar para commit. Caso as modificações sejam um engano e não mais desejadas, você pode desfazazê-las, abadonar a correção/inclusão das palavras usando checkout. Vamos aplicá-lo para ver como funciona.

    cd meu1repo
    
    ## Palavras corrigidas e mais itens adicionados.
    less porqueLinux.txt
    cd meu1repo
    
    ## Abandona modificações feitas presentes no arquivo.
    git checkout -- porqueLinux.txt
    cd meu1repo
    
    less porqueLinux.txt

    Bateu o arrependimento? Tem formas de poder retroceder com mudanças ainda não registradas mas mantendo a possibilidade de recuperá-las. Mostraremos em breve.

    NOTA: sempre que quiser testar um comando novo e não está seguro do que ele faz ou da extensão dos seus efeitos, faça uma cópia do projeto em outro diretório e experimente ele lá. Isso previne sabores amargos, pois algumas ações podem ser irreversíveis.

    cd meu1repo
    
    ## Depois de desfazer as modificações no porqueLinux.txt
    git status

    Vamos seguir com as modificações em porqueLinux.txt que corrigem o texto e acrescentam itens novos.

    cd meu1repo
    
    echo "Por que usar o Linux?
    
    * É livre
    * É seguro
    * É customizável
    * Tem repositórios de software
    * Atualização constante
    * Desempenho" > porqueLinux.txt
    cd meu1repo
    
    git status

    O diff vazio compara o diretório de trabalho com o último registro (último commit). Quando você usa explicitamente na instrução HEAD@{ } seguido de número, então estão sendo comparadas versões "commitadas". Existem variantes de sufixo para usar no HEAD que são:

    • HEAD@{n}
    • HEAD^n
    • HEAD~n

    em que n é um número inteiro não negativo. Cada sulfixo tem uma finalidade que não detalharemos agora. Visite: git-caret-and-tilde.

    cd meu1repo
    
    ## Modificações no diretório vs último commit.
    git diff
    cd meu1repo
    
    ## Último commit vs dois ancestrais, usando ~.
    git diff HEAD~1 HEAD~0
    cd meu1repo
    
    ## Último commit vs seu ancestral, usando @{}.
    git diff HEAD@{1} HEAD@{0}
    cd meu1repo
    
    ## Último commit vs dois ancestrais.
    ## git diff HEAD~2 HEAD~0
    git diff HEAD@{2} HEAD@{0}

    Para ficar claro daqui em diante, você pode ao invés de pedir log, pedir o reflog que incluí as referências em termos da sequência do mais rencente para os seus ancestrais.

    cd meu1repo
    
    ## Mostra referências para commits os ancentrais.
    git reflog
    cd meu1repo
    
    ## Adiciona e commita.
    git add porqueLinux.txt
    git commit -m "Novos argumentos."

    O Git permite um nível de rastreabilidade bem fino. Veja por exemplo que é possível saber quem modificou e quando cada linha do arquivo e qual o correspondente sha1 do commit.

    cd meu1repo
    
    ## Mostra quem, onde e o que fez em cada arquivo.
    git blame README.txt

    Fazendo cópias e trabalhando com ramos

    Existem várias formas de se trabalham com ramos. Geralmente os ramos são feitos sob demandas para adicionar uma característica ao projeto (feature) ou corrigir um bug. Alguns ramos, por outro lado, são ramos fixos destinados a receber o desenvolvimento dos ramos de demanda. Esses ramos são geralmente chamados de devel (development) e release. O ramo master é o default e em geral, para projetos grandes, o master só recebe versões funcionais do projeito, livre de bugs.

    Para criar um ramo, usandos git branch seguido do nome que se deseja. Vamos criar um ramo para adicionar mais arquivos ou modificações ao projeto.

    cd meu1repo
    
    ## Lista ramos (all), locais e remotos.
    ## git branch    ## Só ramos locais
    ## git branch -r ## Só ramos remotos
    git branch -a ## Todos os ramos.
    cd meu1repo
    
    ## Cria um ramo para adição de conteúdo, novo segmento.
    git branch feature01
    cd meu1repo
    
    ## Novo ramo criado aparece.
    git branch
    cd meu1repo
    
    ## Muda o HEAD de ramo.
    git checkout feature01
    cd meu1repo
    
    ## Situação no novo ramo.
    git status
    cd meu1repo
    
    ## Histórico de commits.
    git log --oneline

    Veja que o novo ramo não começa no zero ou vazio (sem arquivos) e sim a partir do ramo que é seu ancestral, ou seja, ele começa a partir do último commit existente, por padrão. Vamos adicionar um arquivo e commitar. O comando wget permite baixar arquivos pelo terminal. Será baixado um arquivo com um função para calcular o fator de inflação de variância (vif, variance inflation factor) usado em modelos de regressão, disponível na página da Professora Suely Giolo.

    ## Tenta ir para o diretório downloads, se não conseguir é porque não
    ## existe então cria um diretório download para então entrar nele.
    if [ -d downloads ]
    then
        echo "Diretório existe."
        cd downloads
    else
        echo "Diretório não existe."
        mkdir downloads
        cd downloads
    fi
    
    ## Se não existir o aquivo vif.R, então baixar da internet.
    if [ ! -f vif.R ]
    then
        echo "Arquivo vif.R não existe. Baixando..."
        wget 'http://people.ufpr.br/~giolo/CE071/Exemplos/vif.R'
    else
        echo "Arquivo vif.R já existe."
    fi
    
    ## Copiar o arquivo vif.R para o meu1repo (-v: verbose).
    cp -v vif.R ../meu1repo/
    cd meu1repo
    
    ## Baixando arquivo da internet. Uma função do R.
    wget 'http://people.ufpr.br/~giolo/CE071/Exemplos/vif.R'
    ## Printa o seria o output da wget mas sem usar a wget para não
    ## encarecer a compilação. Insere o instante da compilação. Esconde
    ## também o IP da máquina com ???.??.???.??.
    
    cat << EOF
    --$(date +"%Y-%m-%d %H:%M:%S")--  http://people.ufpr.br/~giolo/CE071/Exemplos/vif.R
    Resolving people.ufpr.br (people.ufpr.br)... ???.??.???.??, 2801:82:8020:0:8377:0:100:20
    Connecting to people.ufpr.br (people.ufpr.br)|???.??.???.??|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 560
    Saving to: ‘vif.R’
    
         0K                                                       100% 44,0M=0s
    
    $(date +"%Y-%m-%d %H:%M:%S") (44,0 MB/s) - ‘vif.R’ saved [560/560]
    EOF
    cd meu1repo
    
    ## Situação do repositório após o download.
    git status
    cd meu1repo
    
    git add vif.R
    git commit -m "Adiciona função R para VIF."
    cd meu1repo
    
    ## Estrutura do diretório.
    tree
    cd meu1repo
    
    ## Histórico de commits.
    git reflog
    cd meu1repo
    
    git status

    Então acabamos de acrescentar um novo aquivo ao projeto. Agora que as modificações foram salvas (commit feito) podemos trocar de ramo. Você vai ver que ao voltarmos para o ramo master o arquivo baixado da internet vai "desaparecer".

    cd meu1repo
    
    ## Volta para o ramo master.
    git checkout master
    cd meu1repo
    
    ## Estrutura do diretório.
    tree

    O arquivo vif.R não sumiu. Ele está no ramo feature01 e só passará para o ramo master quando mesclarmos o que existe no feature01 ao master. Então é assim: mudou de ramo, muda o conteúdo do diretório. Fazer isso é bem simples, basta dar um git merge. Antes vamos aprender como saber as diferenças que existem entre ramos.

    cd meu1repo
    
    ## Mostra todas as modificações, cada linha modificada de cada arquivo.
    git diff master feature01
    cd meu1repo
    
    ## Mostra só os arquivos modificados.
    git diff --name-only master feature01

    Como você já havia antecipado, a única diferença entre os ramos master e feature01 é o arquivo vif.R. Agora é só pedir o git merge.

    cd meu1repo
    
    ## Mesclando as modificações em feature01 no master.
    git merge feature01 master
    cd meu1repo
    
    git log --oneline

    É possível criar um ramo a partir de um commit ancestral ao atual. Isso é extremamente útil para resolver os bugs. Vamos fazer um segundo ramo a partir do commit anterior a inclusão do arquivo R.

    cd meu1repo
    
    ## Referencias aos commits.
    git reflog
    cd meu1repo
    
    ## Volta para antes do arquivo de baixar o vif.R.
    git checkout HEAD@{4}
    cd meu1repo
    
    ## Qual a situação.
    git status
    cd meu1repo
    
    ## O histório existente nesse ponto.
    git log --name-only --oneline

    Já que o commit mais recente dessa história aponta para o arquivo compras, vamos checar o seu conteúdo apenas por medida de segurança.

    cd meu1repo
    
    ## Mostra o conteúdo do arquivo.
    less porqueLinux.txt

    Dito e feito! Voltamos no tempo para o instante logo após o commit que incluí novos itens na lista. Podemos voltar para o presente se estivermos satisfeitos com o passeio mas também podemos criar um ramo aqui, caso isso seja necessário. Primeiro vamos voltar para o presente depois mostramos como criar o ramo.

    cd meu1repo
    
    ## Mostra onde estamos.
    git branch

    Se não fizemos nenhuma modificação, voltar é bem simples. Se modificações foram feitas é necessário saber se precisam ser mantidas e onde ou se devem ser descartadas.

    cd meu1repo
    
    ## Volta para o presente.
    git checkout master
    cd meu1repo
    
    git status
    cd meu1repo
    
    git log --oneline
    cd meu1repo
    
    ## Fenda no tempo fechada. Sem sinal do detached HEAD.
    git branch
    cd meu1repo
    
    ## Sinal do passeio no tempo.
    git reflog

    Vamos começar a ser ousados. Vamos voltar no passado, adicionar um arquivo, commitar e ver o que acontece, como o histórico é representado.

    cd meu1repo
    
    ## Volta no tempo, após commit que aumenta porqueLinux.txt.
    git checkout HEAD@{6}
    ## Tenta ir para o diretório downloads, se não conseguir é porque não
    ## existe então cria um diretório download para então entrar nele.
    if [ -d downloads ]
    then
        echo "Diretório existe."
        cd downloads
    else
        echo "Diretório não existe."
        mkdir downloads
        cd downloads
    fi
    
    ## Se não existir o aquivo pimentel_racoes.txt, então baixar da internet.
    if [ ! -f pimentel_racoes.txt ]
    then
        echo "Arquivo pimentel_racoes.txt não existe. Baixando..."
        wget 'http://www.leg.ufpr.br/~walmes/data/pimentel_racoes.txt'
    else
        echo "Arquivo pimentel_racoes.txt já existe."
    fi
    
    ## Copiar o arquivo pimentel_racoes.txt para o meu1repo (-v: verbose).
    cp -v pimentel_racoes.txt ../meu1repo/
    cd meu1repo
    
    ## Baixa arquivo de dados da internet.
    wget 'http://www.leg.ufpr.br/~walmes/data/pimentel_racoes.txt'
    ## Printa o seria o output da wget mas sem usar a wget para não
    ## encarecer a compilação. Insere o instante da compilação. Esconde
    ## também o IP da máquina com ???.??.???.??.
    
    cat << EOF
    --(date +"%Y-%m-%d %H:%M:%S")--  http://www.leg.ufpr.br/~walmes/data/pimentel_racoes.txt
    Resolving www.leg.ufpr.br (www.leg.ufpr.br)... ???.??.???.??
    Connecting to www.leg.ufpr.br (www.leg.ufpr.br)|???.??.???.??|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 217 [text/plain]
    Saving to: ‘pimentel_racoes.txt’
    
         0K                                                       100% 68,9M=0s
    
    (date +"%Y-%m-%d %H:%M:%S") (68,9 MB/s) - ‘pimentel_racoes.txt’ saved [217/217]
    
    ‘pimentel_racoes.txt’ -> ‘../meu1repo/pimentel_racoes.txt’
    EOF
    cd meu1repo
    
    git status
    cd meu1repo
    
    ## Adiciona para registrar a inclusão do arquivo.
    git add pimentel_racoes.txt
    git commit -m "Adiciona aquivo de dados de experimento com rações."
    cd meu1repo
    
    git status
    cd meu1repo
    
    ## Log num formato gráfico ASCII para mostrar o novo ramo.
    git log --graph --oneline --decorate --date=relative --all

    No nosso projeto temos o master e o feature01 em igual condição, sem nenhuma diferença. O commit recém feito indica um novo seguimento a partir daquele onde adicionamos novos itens na lista. Vamos criar um novo ramo porque atualmente estamos em um ramos suspenso (detached HEAD) que não é persistênte.

    cd meu1repo
    
    git branch
    cd meu1repo
    
    ## Um novo ramo a partir do atual HEAD.
    git checkout -b feature02
    cd meu1repo
    
    git branch
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all

    Vamos explorar bem a funcionalidade. Vamos voltar para o feature01 e criar mais coisas lá. Você já deve estar pensando que tudo isso é absurdo e jamais alguém firaria indo e voltando assim. Você está certo, porém, quando o projeto envolve mais pessoas, cerrtamente as coisas irão bifurcar em algum ponto.

    cd meu1repo
    
    git checkout feature01
    ## Tenta ir para o diretório downloads, se não conseguir é porque não
    ## existe então cria um diretório download para então entrar nele.
    if [ -d downloads ]
    then
        echo "Diretório existe."
        cd downloads
    else
        echo "Diretório não existe."
        mkdir downloads
        cd downloads
    fi
    
    ## Se não existir o aquivo brasilCopa2014.txt, então baixar da internet.
    if [ ! -f brasilCopa2014.txt ]
    then
        echo "Arquivo brasilCopa2014.txt não existe. Baixando..."
        wget 'http://www.leg.ufpr.br/~walmes/cursoR/geneticaEsalq/brasilCopa2014.txt'
    else
        echo "Arquivo brasilCopa2014.txt já existe."
    fi
    
    ## Copiar o arquivo brasilCopa2014.txt para o meu1repo (-v: verbose).
    cp -v brasilCopa2014.txt ../meu1repo/
    cd meu1repo
    
    wget 'http://www.leg.ufpr.br/~walmes/cursoR/geneticaEsalq/brasilCopa2014.txt'
    ## Printa o seria o output da wget mas sem usar a wget para não
    ## encarecer a compilação. Insere o instante da compilação. Esconde
    ## também o IP da máquina com ???.??.???.??.
    
    cat << EOF
    --$(date +"%Y-%m-%d %H:%M:%S")--  http://www.leg.ufpr.br/~walmes/cursoR/geneticaEsalq/brasilCopa2014.txt
    Resolving www.leg.ufpr.br (www.leg.ufpr.br)... ???.??.???.??
    Connecting to www.leg.ufpr.br (www.leg.ufpr.br)|???.??.???.??|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 1254 (1,2K) [text/plain]
    Saving to: ‘brasilCopa2014.txt’
    
         0K .                                                     100% 69,6M=0s
    
    $(date +"%Y-%m-%d %H:%M:%S") (69,6 MB/s) - ‘brasilCopa2014.txt’ saved [1254/1254]
    EOF
    cd meu1repo
    
    git add brasilCopa2014.txt
    git commit -m "Arquivo sobre copa 2014 celeção brasileira."
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all

    Agora nos temos o feature01 na frente do master e o feature02 ao lado. O conteúdo dos dois ramos terá que ser incorporado ao master em algum momento porque é assim que funciona. Mas não há razões para preocupação pois o propósito do Git é justamente facilitar esse processo. Nesse caso, por exemplo, como as diferenças nos ramos consiste na adição de arquivos diferentes, incorporar as modificações no master será uma tarefa simples para o Git. O agravante é quando em dois ramos (ou duas pessoas) o mesmo arquivo é modificado no mesmo intervalo de linhas. Nessa situação o merge nos arquivos deve ser supervisionado e não automático. Vamos incorporar as modificações dos ramos ao master então.

    cd meu1repo
    
    ## Volta para o master.
    git checkout master
    cd meu1repo
    
    ## Mescla o feature01.
    git merge feature01 master
    cd meu1repo
    
    ## Mescla o feature02.
    git merge feature02 master
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all
    cd meu1repo
    
    tree

    Resolvendo conflitos

    Agora vamos de propósito mostrar uma situação em que não é possível fazer o merge automaticamente. Vamos criar um conflito. Para isso vou criar um ramo novo, modificar o arquivo na última linha e commitar. Vou voltar par ao master e fazer o mesmo mas vou usar um texto diferente para incluir no arquivo. Já que os ramos feature01 e feature02 não são mais necessários, podemos removê-los. No entanto, eles permanecem na história do projeto e poder resurgir se você voltar no tempo.

    cd meu1repo
    
    ## Remove ramos.
    git branch -d feature01
    git branch -d feature02
    git branch
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all

    Agora vou criar um novo ramo, adicionar um arquivo e encurtar o nome das colunas no cabeçalho.

    cd meu1repo
    
    ## Muda para um ramo criado na hora.
    git checkout -b feature03
    ## Tenta ir para o diretório downloads, se não conseguir é porque não
    ## existe então cria um diretório download para então entrar nele.
    if [ -d downloads ]
    then
        echo "Diretório existe."
        cd downloads
    else
        echo "Diretório não existe."
        mkdir downloads
        cd downloads
    fi
    
    ## Se não existir o aquivo bib1.txt, então baixar da internet.
    if [ ! -f bib1.txt ]
    then
        echo "Arquivo bib1.txt não existe. Baixando..."
        wget 'http://www.leg.ufpr.br/~walmes/data/bib1.txt'
    else
        echo "Arquivo bib1.txt já existe."
    fi
    
    ## Copiar o arquivo bib1.txt para o meu1repo (-v: verbose).
    cp -v bib1.txt ../meu1repo/
    cd meu1repo
    
    ## Baixa o arquivo.
    wget 'http://www.leg.ufpr.br/~walmes/data/bib1.txt'
    ## Printa o seria o output da wget mas sem usar a wget para não
    ## encarecer a compilação. Insere o instante da compilação. Esconde
    ## também o IP da máquina com ???.??.???.??.
    
    cat << EOF
    --$(date +"%Y-%m-%d %H:%M:%S")--  http://www.leg.ufpr.br/~walmes/data/bib1.txt
    Resolving www.leg.ufpr.br (www.leg.ufpr.br)... ???.??.???.??
    Connecting to www.leg.ufpr.br (www.leg.ufpr.br)|???.??.???.??|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 535 [text/plain]
    Saving to: ‘bib1.txt’
    
         0K                                                       100% 35,0M=0s
    
    $(date +"%Y-%m-%d %H:%M:%S") (35,0 MB/s) - ‘bib1.txt’ saved [535/535]
    EOF
    cd meu1repo
    
    ## Mostra as 4 primeiras linhas.
    head -4 bib1.txt

    Ao encurtar o nome para quatro dígitos, fica assim.

    cd meu1repo
    
    ## Substitui o conteúdo da primeira linha pelos nomes truncados em 4
    ## dígidos e separados por tabulação. Etapa que você pode fazer no seu
    ## editor de texto.
    sed -i "1s/.*/rept\tvari\tbloc\ty/" bib1.txt
    head -4 bib1.txt
    cd meu1repo
    
    git add bib1.txt
    git commit -m "Arquivo de experimento em BIB. Trunca cabeçalho 4 digitos."

    Baixamos e modificamos o arquivo. Adicionamos e fizemos o registro das modificações. Agora vamos voltar ao master e baixar o arquivo também, fazendo de conta que é outra pessoa trabalhando no mesmo projeto, mas essa pessoa vai passar a cabeçalho para caixa alta.

    cd meu1repo
    
    git checkout master
    ## Copiar o arquivo bib1.txt para o meu1repo (-v: verbose).
    cd downloads
    cp -v bib1.txt ../meu1repo/
    cd meu1repo
    
    ## Baixa o arquivo.
    wget 'http://www.leg.ufpr.br/~walmes/data/bib1.txt'

    Ao encurtar o nome para quatro dígitos, fica assim.

    cd meu1repo
    
    ## Substitui o conteúdo da primeira linha pelo mesmo em caixa alta. Faça
    ## isso no seu editor de texto de preferido.
    sed -i '1s/.*/\U&/' bib1.txt
    head -4 bib1.txt
    cd meu1repo
    
    git add bib1.txt
    git commit -m "Arquivo de experimento em BIB. Cabeçalho em caixa alta."
    cd meu1repo
    
    git diff master feature03
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all
    cd meu1repo
    
    ## Dá mensagem de erro que informa o conflito.
    git merge feature03 master
    x <- system("cd meu1repo && git merge feature03 master", intern=TRUE)
    cat(paste(x, collapse="\n"))
    
    cd meu1repo
    
    git status
    cd meu1repo
    
    ## `less` printa o conteúdo do arquivo mas `head` limita para 10 linhas.
    less bib1.txt | head -10

    Então deu conflito e o Git informa que ele deve ser resolvido. Resolver o conflito aqui significa abrir os arquivos com problema listados no git status e editar de tal forma a desconflitar. Nas regiões de conflito o Git sinaliza de forma especial, indicando por divisórias (<<<<<<<, ======= e >>>>>>>) as versões no HEAD (ramo master) e no ramos a ser incorporado (feature03). Então vamos resolver o conflito sem favorecer ninguém, ou seja, vamos encurtar para 4 digitos e manter caixa alta. Dessa forma o aquivo fica assim.

    cd meu1repo
    
    sed -i '1,3d;5d' bib1.txt
    sed -i '1s/.*/\U&/' bib1.txt
    cd meu1repo
    
    ## Arquivo depois da edição que resolve o conflito.
    head -6 bib1.txt
    cd meu1repo
    
    git status
    cd meu1repo
    
    git add bib1.txt
    git commit -m "Resolve conflito, trunca com caixa alta."
    cd meu1repo
    
    git status
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all
    cd meu1repo
    
    git reflog

    Trabalhando com cópias

    if [ -d ~/maquina2/ ]
    then
        echo "Diretório existe. Então apagar pasta meu1repo."
        cd ~/maquina2/
        ls -a
        if [ -d meu1repo ]
        then
            echo "Já existe meu1repo aqui. Apagar."
            rm -rf meu1repo
        fi
    else
        echo "Diretório não existe."
        mkdir ~/maquina2/
    fi
    
    ## Tudo limpo tal como precisamos.
    pwd
    ls -a
    
    cd meu1repo
    
    git remote -v
    cd ~/maquina2
    
    ## Diretório na segunda que terá uma cópia em desenvolvimento do
    ## projeto.
    pwd
    cd ~/maquina2
    
    ## Conteúdo.
    tree -a
    DIRGIT=$PWD; cd ~/maquina2
    
    ## Clonando o projeto de outro lugar.
    ## $DIRGIT representa o caminho para chegar até meu1repo.
    git clone "$DIRGIT/meu1repo/.git" && cd meu1repo
    cd ~/maquina2/meu1repo
    
    git status
    cd ~/maquina2
    
    ## Conteúdo após clonar.
    tree
    cd ~/maquina2/meu1repo
    
    git remote -v
    cd ~/maquina2/meu1repo
    
    git log --oneline
    cd ~/maquina2/meu1repo
    
    git branch -a
    cd ~/maquina2/meu1repo
    
    git branch feature04
    git checkout feature04
    ## Tenta ir para o diretório downloads, se não conseguir é porque não
    ## existe então cria um diretório download para então entrar nele.
    if [ -d downloads ]
    then
        echo "Diretório existe."
        cd downloads
    else
        echo "Diretório não existe."
        mkdir downloads
        cd downloads
    fi
    
    ## Se não existir o aquivo diasbarros_feijao.txt, então baixar da
    ## internet.
    if [ ! -f diasbarros_feijao.txt ]
    then
        echo "Arquivo diasbarros_feijao.txt não existe. Baixando..."
        wget 'http://www.leg.ufpr.br/~walmes/data/diasbarros_feijao.txt'
    else
        echo "Arquivo diasbarros_feijao.txt já existe."
    fi
    
    ## Copiar o arquivo diasbarros_feijao.txt para o meu1repo (-v: verbose).
    cp -v diasbarros_feijao.txt ~/maquina2/meu1repo/
    cd ~/maquina2/meu1repo
    
    ## Baixa o arquivo.
    wget 'http://www.leg.ufpr.br/~walmes/data/diasbarros_feijao.txt'
    ## Printa o seria o output da wget mas sem usar a wget para não
    ## encarecer a compilação. Insere o instante da compilação. Esconde
    ## também o IP da máquina com ???.??.???.??.
    
    cat << EOF
    --$(date +"%Y-%m-%d %H:%M:%S")--  http://www.leg.ufpr.br/~walmes/data/diasbarros_feijao.txt
    Resolving www.leg.ufpr.br (www.leg.ufpr.br)... ???.??.???.??
    Connecting to www.leg.ufpr.br (www.leg.ufpr.br)|???.??.???.??|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 487 [text/plain]
    Saving to: ‘diasbarros_feijao.txt’
    
         0K                                                       100% 40,2M=0s
    
    $(date +"%Y-%m-%d %H:%M:%S") (40,2 MB/s) - ‘diasbarros_feijao.txt’ saved [487/487]
    EOF
    cd ~/maquina2/meu1repo
    
    git status
    cd ~/maquina2/meu1repo
    
    git add diasbarros_feijao.txt
    git commit -m "Dados de experimento com feijão."
    cd ~/maquina2/meu1repo
    
    git push origin feature04

    Volta para origem e verifica o que recebeu de contribuição.

    cd meu1repo
    
    pwd
    cd meu1repo
    
    git status
    cd meu1repo
    
    git branch -a

    Opa! Tem um novo ramo. Vamos ver o que ele tem de diferente.

    cd meu1repo
    
    git diff --name-only feature04 master

    Parece que chegou um arquivo novo. Vamos então mesclar ao master.

    cd meu1repo
    
    git merge feature04 master
    cd meu1repo
    
    git log --graph --oneline --decorate --date=relative --all
    cd ~/maquina2/meu1repo
    
    pwd
    cd ~/maquina2/meu1repo
    
    git pull origin master
    cd ~/maquina2/meu1repo
    
    git log --graph --oneline --decorate --date=relative --all
    cd ~/maquina2/meu1repo
    
    git log --stat
    cd meu1repo
    
    git log -p -2
    ## STOP
    opts_chunk$set(eval=FALSE)

    Ignorando arquivos e diretórios


    Autenticando em contas do GitLab (c3sl) e GitHub

    Os procedimentos dessa sessão tem o objetivo de promover o conexão da sua máquina de trabalho com sua conta no GitLab do c3sl (alunos UFPR) ou conta do GitHub. Assume-se, logicamente, que você tenha conta em algum desses serviços. Caso você não tenha uma conta em algum serviço de hospedagem de repsitório Git, seguem algumas opções:

    Uma comparação entre os serviços disponíveis para Git está disponível em git-hosting-services-compared.

    Abra o terminal em qualquer diretório. Não precisa ser um diretório Git. Aqui será criado um par de chaves, que nada mais são que longas cadeias de caracteres, de forma que elas formam um par chave/cadeado. A pública (a chave) é copiada para o servidor. A privada fica na sua máquina. Dessa maneira, a comunicação para transferência de dados entre as máquinas pode ser feita.

    Será solicitado uma senha (passphrase). Você pode forncer uma ou apenas pressionar Enter para correr o procedimento padrão. O resultado é uma senha gráfica ASCII além de gerar os arquivos (chaves) cujo caminho é informado no output.

    ## keygen (chave gerar). rsa é o tipo.
    ssh-keygen -t rsa -C "batman@justiceleague.org"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/batman/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/batman/.ssh/id_rsa.
    Your public key has been saved in /home/batman/.ssh/id_rsa.pub.
    The key fingerprint is:
    66:c1:0b:3a:94:25:83:00:81:9f:40:26:f7:aa:af:3a batman@justiceleague.org
    The key's randomart image is:
              +--[ RSA 2048]----+
              |                 |
     ~MMMMMMMMMMMM           MMMMMMMMMMMM~  
        .MMMMMMMMM.   MMM   .MMMMMMMMM.     
          MMMMMMMMMMMMMMMMMMMMMMMMMMM       
           MMMMMMMMMMMMMMMMMMMMMMMMM       
          .MMMMMMMMMMMMMMMMMMMMMMMMM.        
                  .MMMMMMMMM.               
                     .MMM.                  
                       M                    
              |                 |
              +-----------------+

    O importante é o conteúdo do arquivo /home/batman/.ssh/id_rsa.pub, a sua chave pública. Este deve ser fornecido ao GitLab (ou GitHub) em uma janela com as chaves. Os endereços abaixo levam para a mencionada janela. Requer que esteja logado.

    Nessa janela deverá ser informado o código gerado pelo ssh-keygen. Você deve copiar o texto do arquivo /home/batman/.ssh/id_rsa.pub, sem moficá-lo, e fornecer ao GitLab. Para ver/abrir o conteúdo do arquivo no próprio terminal use less ou cat. Para copiar do terminal use ctrl+shift+c. Para abrir com um editor de texto, o gedit por exemplo, é só passar o nome do arquivo.

    ## Abre o arquivo com o editor de texto Gedit.
    gedit /home/batman/.ssh/id_rsa.pub
    
    ## Mostra o conteúdo do arquivo no próprio terminal.
    less /home/batman/.ssh/id_rsa.pub  
    ssh-rsa BBBBB3NzaC1yc2EAAAADAQABAAABAQDDuQmvkQ0WgwYQvR16z37tG37Q61ID+Qf4hi8+cARjjSWP7015CAtRnCvmGFSbdFMjz3ZEkp2XzHIyRCKw2hLP57rkFcfioWra6N5/9+z+tPiwr2OzwLfk7J/GAETGA4rtoToV96hf5RvKRhvuqyO5uf5ouBILm1PRpjA/5AkfToWp25/7WC136eGIOSJMFgQ3OuK5U+qSXAwuSdu9Uj1XkVYFDjasA45ZjsnkE6L9bKiYymadshEbWEBHJAWqDErd8srMtBYS/2hodNnjfH7rNHHCo8wZD5GJFz7YUodaBSaSYuHVfrEryaEm/r5787CAiecFAjWEeVq6StM7N/lz batman@justiceleague.org

    Para conferir a comunicação da sua máquina com o servidor do GitLab do c3sl ou do GitHub, aplique a instrução ssh abaixo.

    ## Com gitlab do c3sl.
    ssh -T git@gitlab.c3sl.ufpr.br
    Welcome to GitLab, Knight Rider!
    ## Com github.
    ssh -T git@github.com
    Hi batman! You've successfully authenticated, but GitHub does not provide shell access.

    Em caso de obter uma mensagem não positiva, repita o comando com a opção -v para um log do procedimento.

    ## Com gitlab do c3sl.
    ssh -vT git@github.com
    OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
    debug1: Reading configuration data /etc/ssh/ssh_config
    debug1: /etc/ssh/ssh_config line 19: Applying options for *
    debug1: Connecting to github.com [192.30.252.130] port 22.
    debug1: Connection established.
    debug1: identity file /home/batman/.ssh/id_rsa type 1
    debug1: identity file /home/batman/.ssh/id_rsa-cert type -1
    debug1: identity file /home/batman/.ssh/id_dsa type -1
    debug1: identity file /home/batman/.ssh/id_dsa-cert type -1
    debug1: identity file /home/batman/.ssh/id_ecdsa type -1
    debug1: identity file /home/batman/.ssh/id_ecdsa-cert type -1
    debug1: identity file /home/batman/.ssh/id_ed25519 type -1
    debug1: identity file /home/batman/.ssh/id_ed25519-cert type -1
    debug1: Enabling compatibility mode for protocol 2.0
    debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3
    debug1: Remote protocol version 2.0, remote software version libssh-0.7.0
    debug1: no match: libssh-0.7.0
    debug1: SSH2_MSG_KEXINIT sent
    debug1: SSH2_MSG_KEXINIT received
    debug1: kex: server->client aes128-ctr hmac-sha1 none
    debug1: kex: client->server aes128-ctr hmac-sha1 none
    debug1: sending SSH2_MSG_KEX_ECDH_INIT
    debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
    debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
    debug1: Host 'github.com' is known and matches the RSA host key.
    debug1: Found key in /home/batman/.ssh/known_hosts:1
    debug1: ssh_rsa_verify: signature correct
    debug1: SSH2_MSG_NEWKEYS sent
    debug1: expecting SSH2_MSG_NEWKEYS
    debug1: SSH2_MSG_NEWKEYS received
    debug1: Roaming not allowed by server
    debug1: SSH2_MSG_SERVICE_REQUEST sent
    debug1: SSH2_MSG_SERVICE_ACCEPT received
    debug1: Authentications that can continue: publickey
    debug1: Next authentication method: publickey
    debug1: Offering RSA public key: /home/batman/.ssh/id_rsa
    debug1: Server accepts key: pkalg ssh-rsa blen 279
    debug1: Authentication succeeded (publickey).
    Authenticated to github.com ([192.30.252.130]:22).
    debug1: channel 0: new [client-session]
    debug1: Entering interactive session.
    debug1: Sending environment.
    debug1: Sending env LC_PAPER = pt_BR.UTF-8
    debug1: Sending env LC_ADDRESS = pt_BR.UTF-8
    debug1: Sending env LC_MONETARY = pt_BR.UTF-8
    debug1: Sending env LC_NUMERIC = pt_BR.UTF-8
    debug1: Sending env LC_TELEPHONE = pt_BR.UTF-8
    debug1: Sending env LC_IDENTIFICATION = pt_BR.UTF-8
    debug1: Sending env LANG = en_US.UTF-8
    debug1: Sending env LC_MEASUREMENT = pt_BR.UTF-8
    debug1: Sending env LC_TIME = pt_BR.UTF-8
    debug1: Sending env LC_NAME = pt_BR.UTF-8
    debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
    Hi batman! You've successfully authenticated, but GitHub does not provide shell access.
    debug1: channel 0: free: client-session, nchannels 1
    Transferred: sent 3856, received 1784 bytes, in 0.4 seconds
    Bytes per second: sent 10261.9, received 4747.7
    debug1: Exit status 1

    Requisições de mescla

    Colaborando via fork


    Modelos de fluxos de trabalho


    Usando ferramentas gráficas para o Git

    Git GUI

    Gitk

    Meld


    Dicionário de termos