git_tuto.Rmd
-
Walmes Marques Zeviani authoredWalmes Marques Zeviani authored
- O que é o Git?
- Download e instalação
- Configurando perfil
- Criar um projeto versionado
- Instruções do Git
- Criar um diretório para o projeto Git
- Fazendo cópias e trabalhando com ramos
- Resolvendo conflitos
- Trabalhando com cópias
- Ignorando arquivos e diretórios
- Autenticando em contas do GitLab (c3sl) e GitHub
- 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
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
- Tobias Günther;
- GitHub git cheat sheet
- Chris Sevilleja
- Jan Krüger
- William Leeks
- cheat.errtheblog.com
O modelo de funcionamento do Git:
Playlists de tutoriais de Git
- Loiane Groner - Git e Github para iniciantes
- HxTutors - Github - Pra que serve e como usar?
- Devmedia Editora - Controle de versoes distribuido com Git
- RBtech - Curso básico de Git (playlist)
- Luiz Venturote - Controle de Versão com Git
- Leandro Cavalcante Git (playlist)
- StudyClassOficial - Controle de Versão com GIT
- Israel Santos - Controle de versão com git
- Giovanni Silva - Tutorial Git (playlist)
- makigas - Tutorial de Git en media hora
- Desde Cero - Cómo Instalar Git en Windows Desde Cero
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:
- GitHub: https://github.com/
- GitLab: https://about.gitlab.com/
- Bitbucket: https://bitbucket.org/
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