---
# System prepended metadata

title: 'Roteiro detalhado: Git'

---

# Sumário

[TOC]

# Versionadores

### O que são e por que surgiram? 
- São sistemas que registram alterações em um arquivo ou conjunto de arquivos ao longo do tempo para que você possa lembrar versões específicas mais tarde.

- Surgiram devido a necessidade do aumento da eficiência, do aumento do número de colaboradores e do gerenciamento de projetos de software moderno.

![Captura de tela 2024-06-04 094408](https://hackmd.io/_uploads/ryblu7zSR.png)

### Tipos de Versionadores

Sistemas de controle de versão podem ser: **locais**, **centralizados** ou **distribuídos**.

- Sistemas **locais** de controle de versão tem um banco de dados simples que mantêm todas as alterações nos arquivos sob controle de versão.

    ![Captura de tela 2024-06-04 101220](https://hackmd.io/_uploads/SJv-sbGHA.png)

- Sistemas **centralizados** de controle de versão têm um **único servidor** que contém todos os arquivos de controle de versão, e um número de clientes que usam arquivos a partir desse lugar central. Por muitos anos, este foi o padrão para controle de versão. Um **defeito grave** desses versionadores é que se o servidor der problema por uma hora, durante essa hora ninguém pode colaborar ou salvar as alterações de versão para o que quer que eles estejam trabalhando. 


    - Os primerios Modelos surgiram descentralizados
    - Necessidade de estar conectado ao servidor central
    - Para equiper pequenas
    - Mais simples de Utilizar
    - Wikipédia se utiliza desse modelo

![Captura de tela 2024-06-11 092630](https://hackmd.io/_uploads/By_qMTBHR.png)



![Captura de tela 2024-06-04 101557](https://hackmd.io/_uploads/HJUGsZzB0.png)

- Já em sistemas **distribuídos** de controle de versão, os clientes não somente usam o estado mais recente dos arquivos, mas também duplicam localmente o repositório completo. Cada clone é um backup completo de todos os dados.
![descentralizado](https://hackmd.io/_uploads/SJpghZzrA.png)
Nesse curso estudaremos um dos sistemas de versionamento mais usados do mundo: o Git.

    - Escalabilidade
    - Não depende de um servidor central
    - Maior eficiência
    - Maior segurança a ataques 

![Captura de tela 2024-06-11 092957](https://hackmd.io/_uploads/S12LXpBHA.png)

![upscayledImage](https://hackmd.io/_uploads/ry_kclLHA.png)

# História do Git:
### Como surgiu?

Como vimos durante o curso, Linux kernel é um projeto de software livre de grande prote. Durante os anos iniciais de criação e manutenção desse sistema, mudanças do software eram feitas a partir do envio de arquivos entre os desenvolvedores e, um tempo depois, passaram a serem feitas usando o versionador BitKeeper.
    
Na época em que o BitKeeper passou a ser pago, a comunidade Linux (em especial, Linus Torvalds) passou a desenvolver sua própria ferramenta baseada em lições que haviam aprendido durante os anos usando o BitKeeper. Esses eram alguns dos objetivos do sistema:
- Velocidade
- Design simples
- Forte suporte para o desenvolvimento não linear (milhares de branches paralelas)
- Altamente distribuído
- Ter a capacidade de lidar com grandes projetos como o Linux kernel de forma eficiente
### De onde vem o nome "Git"?
Git é uma gíria britânica para "pessoa desagradável".
   
Linus Torvalds disse sarcasticamente em uma entrevista: "eu sou um egoísta e nomeio todos os meus projetos em minha homenagem. Primeiro 'Linux' e agora 'git'".
    
Se você estiver de bom humor, pode significar 'Global Information Tracker'.
    
Vejam o manual do git usando o terminal ('man git').



### Git como um versionador
![descentralizado](https://hackmd.io/_uploads/SJpghZzrA.png)


1.   Open Source
2.   Trabalho em equipe
3.   Desenvolvimento de softwares de todos os tipos
4.   O mais utilizado atualmente


- Como o Git funciona?
Sabemos que o Git é um versionador, ou seja, é uma ferramenta que tem a finalidade de gerenciar diferentes versões no desenvolvimento de um arquivo ou conjunto de arquivos.
    - Com o Git, sempre que você salta o estado do projeto, é "tirada uma foto" de como os arquivos estavam naquele momento e salva uma referência a esse snapshot. Por eficiência, se um arquivo não foi modificado, ele não o salva o arquivo novamente, mas apenas um "link" para a versão anterior que já está salva.
    
![image](https://hackmd.io/_uploads/SkYli-6zR.png)
    
- Quase todas as operações são locais
    -Com o Git, todo o histórico do projeto é armazenado localmente, fazendo com que as operações sejam quase intantâneas. Comparar versões antigas do seu projeto pode ser feito localmente sem a necessidade de interagir com o servidor remoto.

- O Git, no geral, apenas **adiciona** informações
    -É difícil fazer com que o sistema apague dados ou faça algo irreversível, principalmente se você der pushes regulares do seu trabalho(enviar as suas alterações para o servidor remoto constantemente).

# Github & Shell
### Introdução a plataformas de hospedagem remota
-  Git Lab, Codeberg e BitBucket

 - ![Design sem nome](https://hackmd.io/_uploads/rJ9yYGwH0.png)
 
 - O que eles têm em comum? 
     - Todos são plataformas onde é possível hospedar repositórios. 

### Github
- Hospedagem de Repositórios
- Se utiliza do git para fazer o controle de versão dos respositórios hospedados
- Comunidade ativa
- Vários outros serviços
- Um dos maiores repositórios de projetos open source do mundo

Github é a maior plataforma de hospedagem para repositórios Git, além de ser o ponto central de colaboração para milhões de desenvolvedores.
Grande parte dos repositórios Git estão hospedados no Github e muitos projetos de código aberto o usam para hospedagem, monitoramento de problemas e tarefas, revisão de código etc.

> O git e o github são a mesma coisa? 
>> Não, Github e similares como GitLab e Bitbucket, são provedores que utilizam o git, fornecendo uma interface visual, além de armazenamento na nuvem para os projetos.


### Chave SSH 

-  **Para que serve a chave SSH?**

    As chaves SSH (Secure Shell) são utilizadas para autenticar conexões seguras entre computadores, permitindo uma comunicação criptografada. Elas substituem a necessidade de senhas tradicionais, proporcionando uma maneira mais segura e conveniente de acessar sistemas remotos e serviços, como repositórios Git.

    Ao configurar uma chave SSH, você cria um par de chaves: uma chave privada, que deve ser mantida em segredo no seu computador, e uma chave pública, que é adicionada ao servidor ou serviço remoto. Quando uma conexão é iniciada, o servidor usa a chave pública para verificar a identidade do usuário, sem que a chave privada precise ser transmitida pela rede, garantindo assim a segurança.

    No contexto do Git, a autenticação via chave SSH é especialmente útil ao interagir com repositórios remotos hospedados em plataformas como GitHub, GitLab e Bitbucket. Essas plataformas suportam autenticação por chave SSH, permitindo que os desenvolvedores enviem (push) e busquem (pull) alterações de forma segura, sem precisar digitar senhas repetidamente.


# Um pouco mais sobre Git
### Como ele lida com informações

O Git é um sistema de controle de versão distribuído que gerencia informações armazenando cada versão do projeto como um snapshot completo, em vez de apenas as diferenças entre versões. Ele utiliza uma estrutura de objetos que inclui blobs (conteúdo de arquivos), trees (diretórios), commits (mudanças com metadados) e tags (marcadores de versão). Cada objeto é identificado por um hash SHA-1, garantindo a integridade dos dados. Git permite a criação de branches para desenvolvimento paralelo e merges para combinar mudanças. As modificações são preparadas na staging area antes de serem commitadas. Com funcionalidades robustas de colaboração e resolução de conflitos, Git suporta operações offline e sincronização com repositórios remotos através de comandos como push e pull, facilitando o trabalho simultâneo de múltiplos desenvolvedores.


### Workflow básico
1) Você **modifica arquivos** na sua árvore de trabalho
2) Você **seleciona apenas as mudanças que você quer** que façam parte do seu próximo commit, e apenas essas mudanças serão adicionadas à staging area
3) Você **faz um commit**: os arquivos como eles estão na staging area são armazenados em forma de snapshot permanentemente no seu diretório  Git.

    ![image](https://hackmd.io/_uploads/HJKOTMTGC.png)

Assim, podemos perceber que um arquivo pode estar em um dos 3 estados:
* modified
* staged
* commited


### Lidando com repositórios
No final desta sessão, você será capaz de **configurar** e **inicializar** um repositório, iniciar e interromper o **rastreamento de arquivos**, usar a **área de stage** e realizar **commits** das alterações. 

Também mostraremos como configurar o Git para ignorar certos arquivos e padrões de arquivo,como desfazer erros de maneira rápida e fácil, como navegar no histórico do seu projeto e visualizar alterações entre commits e como fazer push e pull em repositórios remotos.

- **Obtendo um repositório Git**

Você pode obter um repositório de duas formas principais:
    1) Pegando um diretório local que não está sob controle de versão e transaformando-o em um repositório
    2) Fazendo um clone de um repositório Git existente em outro lugar
    
Por enquanto, vamos lidar apenas com repositórios locais.

**Inicializando um repositório em um diretório existente:**

```
 cd new_repository
 git init
```

Agora, temos um subdiretório chamado .git que contém todos os arquivos necessários de seu repositório – um esqueleto de repositório Git. Nada em seu projeto é monitorado ainda.
![Captura de tela 2024-06-11 094114](https://hackmd.io/_uploads/BJL-L6rHA.png)

> Quando fazemos o comando git init no local/diretório onde queremos criar um repositório, uma pasta oculta é criada chamada".git", que vai ter as configurações necessárias para o monitoramento do git naquele diretório.

![Captura de tela 2024-06-11 094203](https://hackmd.io/_uploads/SyhQUaSB0.png)

-  **Gravando alterações em seu repositório**

Cada arquivo em seu repsitório pode estar em um dos seguintes estados: rastreado e não-rastreado. Arquivos rastreados são arquivos que foram incluídos no último snapshot; eles podem ser não modificados, modificados ou preparados (adicionados ao stage). Em resumo, arquivos rastreados são os arquivos que o Git conhece.

Quando você clona um repositório pela primeira vez, todos os seus arquivos serão rastreados e não modificados já, que o Git acabou de obtê-los e você ainda não editou nada.

Assim que você edita alguns arquivos, Git os considera modificados, porque você os editou desde o seu último commit. Você prepara os arquivos editados e então faz commit das suas alterações, e o ciclo se repete.

![image](https://hackmd.io/_uploads/SJWWiARzC.png)

<!-- Aqui será feito o primeiro repositório remoto seguindo os passos do github -->

# Lidando com o git

### Verificando os status de seus arquivos

A principal ferramenta que você vai usar para determinar quais arquivos estão em qual estado é o comando git status.

```sh
    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    nothing to commit, working directory clean
```

Digamos que você adiciona um novo arquivo no seu projeto, um simples arquivo README. Se o arquivo não existia antes, e você executar git status, você verá seu arquivo não rastreado da seguinte forma:

 ```sh
    $ echo 'My Project' > README
    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Untracked files:
    (use "git add <file>..." to include in what will be committed)

        README

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

Nós queremos incluir esse arquivo README, então vamos rastreá-lo.

### Rastreando arquivos novos
Para começar a rastrear um novo arquivo, você deve usar o comando git add

    $ git add README
    
Executando o comando status novamente, você pode ver que seu README agora está sendo rastreado e preparado (staged) para o commit:

    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)

        new file:   README
        
É possível saber que o arquivo está preparado porque ele aparece sob o título “Changes to be committed”. Se você fizer um commit neste momento, a versão do arquivo que existia no instante em que você executou git add, é a que será armazenada no histórico de snapshots.

### Preparando Arquivos Modificados (Adicionando arquivos modificados à staging area)

Vamos modificar um arquivo que já está sendo rastreado.

Se modificarmos o CONTRIBUTING.md que já era rastreado, e executarmos o `git status`, teremos isso:

    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)

        new file:   README

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

        modified:   CONTRIBUTING.md
        
Isso significa que o arquivo rastreado foi modificado no diretório mas ainda não foi mandado para o stage (preparado).

Para isso, vamos usar o `git add`.

Pode ser útil pensar nesse comando mais como “adicione este conteúdo ao próximo commit”.

    $ git add CONTRIBUTING.md
    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)

        new file:   README
        modified:   CONTRIBUTING.md
        
:::info
Ao mesmo tempo que a saída do git status é bem completa, ela também é bastante verbosa. O Git também tem uma flag para status compacto.

    $ git status -s
     M README
    MM Rakefile
    A  lib/git.rb
    M  lib/simplegit.rb
    ?? LICENSE.txt
:::

### Fazendo commit das suas alterações
Agora que a área de stage está preparada, podemos fazer commit nas alterações.

O jeito mais simples de fazer commit é digitar o seguinte comando:

    $ git commit

e adicionar uma mensagem no editor de texto.

Alternativamente, podemos fazer:

    $ git commit -m "mensagem"
    
Lembre-se de que o commit grava o snapshot que você deixou na área de stage. Qualquer alteração que você não tiver mandado para o stage permanecerá como estava, em seu lugar; você pode executar outro commit para adicioná-la ao seu histórico. Toda vez que você executa um commit, você está gravando um snapshot do seu projeto que você pode usar posteriormente para fazer comparações, ou mesmo restaurá-lo.

###  Como ver todos os commit feitos? - O comando git log

É um comando feito para exibir os históricos de commits do projeto.

Aparece nome, hora, data e a mensagem relacionada a cada commit.
![Captura de tela 2024-06-08 164219](https://hackmd.io/_uploads/ByYVV4MHC.png)
> Dica: para sair da tela é só digitar "q"

- **Uma flag eficiente**
 
    ```
    $git log --oneline
    ``` 
    
![Captura de tela 2024-06-08 164718](https://hackmd.io/_uploads/BJJOrVGSR.png)

Essa flag apresenta os commits feitos de uma forma bem mais simples: apresenta o código referente ao commit e a respectiva mensagem.

### Subindo auterações para o repositório remoto `git push`

Se você tem um commit pronto e quer adiciona-lo ao repositório remoto, podemos fazer:

    $ git push 
    
Fazendo o git push os seus commits irão subir para o seu repositório remoto.



<!--Primeiro exercício usando git commit-->

### Visualizando commits anteriores
- Git checkout <endereço do commit> 
    
Ao utilizar `git checkout` você consegue visualizar como estavam os seus arquivos para um commit específico.
    ![Captura de tela 2024-06-11 101121](https://hackmd.io/_uploads/BJ7zaaHSR.png)
    
- Note que agora quando fazemos o comando git log --oneline ele mosta apenas os commits anteriores ao escolhido para visualizar.
    
- Não perdemos as outras alterações, apenas voltamos no tempo para ver como estava o nosso projeto naquele commit em específico.
    
![Captura de tela 2024-06-11 101214](https://hackmd.io/_uploads/HyjraprHR.png)

- Para voltar ao commit de onde paramos, precisamos fazer o commando `git  checkout <nomedabranch>`, como feito na imagem abaixo.
    
![Captura de tela 2024-06-11 101719](https://hackmd.io/_uploads/HyJFCprBA.png)
    
### Revertendo commits
- Ao utilizar o `git revert` podemos reverter um commit que foi realizado, para o seu estado original. Basicamente será feito um novo commit para a reversão

   - **git revert HEAD**
      Este comando vai reverter o commit mais recente
    ![Captura de tela 2024-06-11 132920](https://hackmd.io/_uploads/SkIkhxUS0.png)
        >Acima temos todos os commits feitos em um arquivo txt chamado facebook    

        ![Captura de tela 2024-06-11 132856](https://hackmd.io/_uploads/H1yx2g8SC.png)
        > Note acima como está o estado atual do documento 
        > Vamos utilizar o comando "git revert HEAD"
        > Após isso, aparece a seguinte página.
    
        ![Captura de tela 2024-06-11 132950](https://hackmd.io/_uploads/Hy3e2x8SR.png)
        
        > para sair dela digite ":q"

        ![Captura de tela 2024-06-11 133010](https://hackmd.io/_uploads/S1IWnl8S0.png)
        > Note acima que o último commit que foi a criação do "feedline" foi revertido e só temos o chat.
    
    
        ![Captura de tela 2024-06-11 140247](https://hackmd.io/_uploads/HyMcX-IBR.png)
    
        > Note que o comando reverte  o commit criando outro commit com essa reversão
    
    - **git revert <endereço do commit>**
        Reverte o commit indicado, ou seja, a auteração que foi feita neste commit será retirada.
        
        > Observe o seginte exemplo: 
        
        Vamos criar um repositório chamado facebook e crie três arquivos chamdo estrutura.txt, chat.txt e  timeline.txt, fazendo um commit a cada arquivo criado.    
    
        ![Captura de tela 2024-06-11 143623](https://hackmd.io/_uploads/H12IiZLBC.png)
        >Faça no terminal o seguinte comando "git revert 7d2b5e1"
        > Note que vai aparecer a seguinte tela
    
        ![Captura de tela 2024-06-11 143832](https://hackmd.io/_uploads/H1_osWLH0.png)
        
        > Escreva ":q"  para finalizar a reversão
    
        ![Captura de tela 2024-06-11 143920](https://hackmd.io/_uploads/By7y2-Lr0.png)
        > volte na sua página e note que o arquivo com nome "chat.txt"  foi retirado, pois ele tinha sido criado naquele commit.

    <div style="border: 2px solid red">
    Nessa parte poderiamos mostrar resolução de conflitos , um exemplo bem simples com um arquivo com 4 linhas, cada linha um commit. Poderiamos tentar reverter o segundo commit, vai dar um conflito e resolvemos.
        
    - **git revert     - -abort**
        Aborta uma reversão que etá em andamento
        
    - **git revert     - -continue**
        Continua uma reversão que está em andamento
    </div>
   
### Desfazendo coisas

- **Ajustando commits**

Aqui devemos tomar cuidado, porque nem sempre você pode voltar uma alteração desfeita. Essa é uma das poucas áreas do Git onde pode perder algum trabalho feito se você cometer algum engano.

Se você fez um commit cedo demais e esqueceu de adicionar alguns arquivos ou quer corrigir a mensagem, você pode refazer o commit usando a opção --amend:

    $ git commit --amend
    
Esse comando pega a área stage e a usa para realizar o commit. Se você não fez nenhuma alteração desde o último commit (por exemplo, se você executar o comando imediatamente depois do commit anterior), então sua imagem dos arquivos irá ser exatamente a mesma, e tudo o que você alterará será a mensagem do commit.

O mesmo editor de mensagens de commit é acionado, porém o commit anterior já possui uma mensagem. Você pode editar a mensagem como sempre, porém esta sobrescreve a mensagem do commit anterior.

Também podemos fazer dessa forma:

    $ git commit -m 'initial commit'
    $ git add forgotten_file
    $ git commit --amend
    
No final das contas, o segundo commit substituiu o resultante do primeiro.

- **Retirando um arquivo do Stage**

Se você alterou dois arquivos, e deseja realizar o commit deles separadamente, porém você acidentalmente digitou `git add *` adicionando ambos ao stage. Como você pode retirar um deles do stage? O comando git status lhe lembrará de como fazer isso:

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

        renamed:    README.md -> README
        modified:   CONTRIBUTING.md
        
Logo abaixo do texto “Changes to be committed”, diz `git reset HEAD <file>...` para retirar o arquivo do stage. Então, vamos usar esta sugestão para retirar o arquivo CONTRIBUTING.md do stage:
    
    $ git reset HEAD CONTRIBUTING.md
    Unstaged changes after reset:
    M	CONTRIBUTING.md
    $ git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)

        renamed:    README.md -> README

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

        modified:   CONTRIBUTING.md
        
O arquivo CONTRIBUTING.md volta ao estado modificado porem está novamente fora do stage.

- **Desfazendo mofificações me um arquivo**

E se você se der conta de que na verdade não quer manter as modificações do arquivo CONTRIBUTING.md? Como você pode reverter as modificações, voltando a ser como era quando foi realizado o último commit (ou clone inicial, ou seja como for que você chegou ao seu working directory)? Felizmente, git status diz a você como fazer isso também. Neste último exemplo, a área fora do stage parece com isso:

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

        modified:   CONTRIBUTING.md

Isso lhe diz de forma explícita como descartar as modificações que você fez. Vamos fazer o que o comando nos sugeriu:

    $ git checkout -- CONTRIBUTING.md
    $ git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)

        renamed:    README.md -> README

Você pode notar que as modificações foram revertidas.

### Trabalhando de forma remota

- **O que são repositórios remotos?**

Para colaborar com qualquer projeto Git, você precisará saber como gerenciar seus repositórios remotos. Repositórios remotos são versões de seu repositório hospedado na Internet ou em uma rede qualquer. 

Colaborar com outras pessoas envolve o gerenciamento destes repositórios remotos, fazer pushing(atualizar) e pulling(obter) de dados para e deles quando você precisar compartilhar seu trabalho.

- **Adicionando repositórios remotos**

Caso você já tenha um repositório local, é possível torná-lo um repositório remoto executando o comando `git remote add <shortname> <url>`

    $ git remote add meu-repositorio https://github.com/marina/meu-repositorio
    
Agora, o seu repositório local estará ligado a esse repositório remoto

Tá, mas e agora? Como eu coloco o que eu já tenho no meu repositório local no GitHub?

- **Dando push para um repositório remoto**
Se você tem um commit pronto e quer adiciona-lo ao repositório remoto, podemos fazer:

    $ git push origin master
    
Por enquanto ainda não sabemos o que "master" significa, mas descobriremos na próxima seção.

- **Clonando um repositório existente:**
Para isso, vamos usar o comando `git clone`. Com esse comando, o Git recebe uma cópia completa de praticamente todos os dados que o servidor possui. Cada versão de cada arquivo do histórico do projeto é obtida quando você executa o git clone.

- **Dando pull em um repositório remoto**
O comando `git pull` é usado para buscar e baixar conteúdo de repositórios remotos e fazer a atualização imediata ao repositório local para que os conteúdos sejam iguais.
    
    
## Git branching


Branches são ramificações para criar ramos de desenvolvimento, tipo versões. Nessas ramificações podemos criar diferentes recursos que depois serão mesclados.

![334154431-2eb608f8-a923-4ca5-8f1f-d1f63471febe](https://hackmd.io/_uploads/HJ82XGzBC.png)
Conforme ilustrado na imagem fornecida, os pontos azuis representam uma branch criada especificamente para desenvolver a funcionalidade de chat de um app como o facebook. Esta branch está separada do projeto principal, permitindo que os desenvolvedores trabalhem no novo recurso sem interferir na base de código principal.
Isso nos permite evitar de causar problemas no ramo principal, em quanto estamos desenvolvendo novas funcionalidades.
 
### As vantagens do uso de branchs:
1. **Isolamento**: Encapsular o desenvolvimento de novos recursos em uma branch separada evita alterações acidentais no projeto principal, garantindo estabilidade e integridade.
2. **Desenvolvimento Paralelo**: Múltiplos desenvolvedores podem trabalhar em diferentes recursos simultaneamente sem conflitos ou interrupções, aumentando a produtividade e a eficiência.
3. **Teste e Refinamento**: Novos recursos podem ser testados e refinados minuciosamente dentro da branch antes de serem mesclados na base de código principal, garantindo uma experiência do usuário de alta qualidade.


### Branches em uma casca de pitomba
1) Vamos fazer o commit de um diretório com 3 arquivos
    - Agora, o seu repositório tem 5 objetos:
        - 3 blobs (arquivos)
        - um commit com o ponteiro para a raíz da árvore
        - os metadados do commit
![image](https://hackmd.io/_uploads/S1hzEwpMC.png)

    Se você fizer alguma alteração no diretório e commitar novamente, esse último commit armazenará um ponteiro para o commit que veio antes dele.
![image](https://hackmd.io/_uploads/HJBKVDafR.png)

    Uma branch no Git é simplesmente um ponteiro móvel para um desses commits. O nome da branch padrão no Git é master. Conforme você começa a fazer commits, você recebe uma branch master que aponta para o último commit que você fez. Cada vez que você faz um novo commit, ele avança automaticamente.

:::    info
A branch **'master'** no Git não é uma branch especial. Todo repositório tem uma porque o comando git init a cria por padrão e a maioria das pessoas não muda isso.
:::

2) Criando uma nova branch
    Criar uma nova branch cria um novo ponteiro para você mover.
    ```
    $ git branch testing
    ```
    ![image](https://hackmd.io/_uploads/S1qgUwTzC.png)
    
    Como o git sabe onde eu estou agora? Ele tem um ponteiro especial chamado HEAD.

    ![image](https://hackmd.io/_uploads/rJ1SLDpMR.png)

    Observe que o comando *git branch* apenas criou uma nova branch.
    Para mudar de branch, devemos executar o comando
    
    ```
    $ git checkout testing
    ``` 
    
    ![image](https://hackmd.io/_uploads/ryMwi_pGA.png)

    Tá. Mas o que isso muda? Veja o que acontece quando fazemos outro commit:

    ![image](https://hackmd.io/_uploads/SJ4mnuTGC.png)

    Observe que a branch testing avançou, mas a master continua apontado para o commit que estava quando você executou o checkout para alternar entre as branches.

    Podemos voltar para a master:
    
    ```
    $ git checkout master
    ```

    ![image](https://hackmd.io/_uploads/S1HNAupGC.png)

    E se você fizer um commit na master? O que acontece?

    ![image](https://hackmd.io/_uploads/BJ7rRd6zC.png)

    Agora, o histórico do seu projeto divergiu.

    Ambas as mudanças feitas são isoladas em branches separadas: você pode alterar entre essas ramificações e mesclá-las quando quiser.

Tudo o que fizemos até agora foi bem simples. Usamos apenas os comandos:
- Branch
- Checkout
- Commit

## Mesclagem (merging)

- Ramificação e mesclagem simples

Primeiramente, digamos que você esteja trabalhando em seu projeto e já tenha alguns commits na branch master.

Você decidiu que você vai trabalhar no chamado #53 em qualquer que seja o sistema de gerenciamento de chamados que a sua empresa usa.

Para criar uma nova branch e mudar para ele ao mesmo tempo, você pode executar o comando git checkout com o parâmetro -b:

    $ git checkout -b iss53
    Switched to a new branch "iss53"
    
Esta é a abreviação de:

    $ git branch iss53
    $ git checkout iss53

![image](https://hackmd.io/_uploads/rJh5srfm0.png)

Ao fazer isso, você move o branch iss53 para a frente, pois este é o branch que está selecionado, ou checked out(isto é, seu HEAD está apontando para ele):

    $ vim index.html
    $ git commit -a -m 'Create new footer [issue 53]'

![image](https://hackmd.io/_uploads/SJIniSfQ0.png)

Porém, um problema importante surgiu e precisamos corrigí-lo imediatamente. Então, vamos voltar para a branch master e criar uma outra branch a partir de lá.

Entretanto, antes de fazer isso, note que se seu diretório de trabalho o stage possui alterações ainda não commitadas que conflitam com a branch que você quer usar, o Git não deixará que você troque de branch. O melhor é que seu estado de trabalho atual esteja limpo antes de trocar de branches, então, se você não tiver dado commit em suas alterações, certifique-se de fazer isso.

Agora sim poderemos mudar para a master:

    $ git checkout master
    Switched to branch 'master'
    
Neste ponto, o diretório de trabalho de seu projeto está exatamente da forma como estava antes de você começar a trabalhar no chamado #53, e você pode se concentrar na correção.

Seu próximo passo é fazer a correção necessária; Vamos criar uma branch chamado hotfix no qual trabalharemos até a correção estar pronta:

    $ git checkout -b hotfix
    Switched to a new branch 'hotfix'
       
    $ git commit -a -m 'Fix broken email address'
    [hotfix 1fb7853] Fix broken email address
     1 file changed, 2 insertions(+)

![image](https://hackmd.io/_uploads/HJYF6SfXA.png)

Você pode executar seus testes, se assegurar que a correção está do jeito que você quer, e finalmente mesclar a branch hotfix de volta para a branch master para poder enviar para produção. Para isso, você usa o comando git merge:

    $ git checkout master
    $ git merge hotfix
    Updating f42c576..3a0874c
    Fast-forward
     index.html | 2 ++
     1 file changed, 2 insertions(+)
     
Você vai notar a expressão “fast-forward” nesse merge. Isso ocorre porque a branch `hotfix`que você mesclou aponta para o commit `c4`, que está diretamente à frente do commit `c2`, no qual você está agora, então o Git simplesmente move o ponteiro da branch master para a frente.

Um merge fast-forward ocorre quando você tenta mesclar um commit A com outro commit B que pode ser alcançado por meio do histórico linear do commit A.

![image](https://hackmd.io/_uploads/SyS428z7R.png)

Assim que a sua correção importantíssima é entregue, você já pode voltar para o trabalho que estava fazendo antes da interrupção. Porém, você irá antes excluir o branch hotfix, pois ele já não é mais necessário — o branch master aponta para o mesmo lugar. Você pode remover o branch usando a opção -d com o comando git branch:

    $ git branch -d hotfix
    Deleted branch hotfix (3a0874c).

Agora você pode retornar à branch com seu trabalho em progresso na issue #53 e continuar trabalhando.

    $ git checkout iss53
    Switched to branch "iss53"
    $ vim index.html
    $ git commit -a -m 'Finish the new footer [issue 53]'
    [iss53 ad82d7a] Finish the new footer [issue 53]
    1 file changed, 1 insertion(+)

É importante frisar que o trabalho que você fez na sua branch hotfix não está contido nos arquivos do seu branch iss53. Caso você precise dessas alterações, você pode fazer o merge da branch master na branch iss53 executando git merge master, ou você pode esperar para integrar essas alterações até que você decida mesclar a branch iss53 de volta para master mais tarde.

- Outra forma de mesclagem

Digamos que você decidiu que o seu trabalho no chamado #53 está completo e pronto para ser mesclado de volta para a branch master. Para fazer isso, você precisa fazer o merge da branch iss53, da mesma forma com que você mesclou a branch hotfix anteriormente. Tudo o que você precisa fazer é mudar para a branch que receberá as alterações e executar o comando git merge:

    $ git checkout master
    Switched to branch 'master'
    $ git merge iss53
    Merge made by the 'recursive' strategy.
    index.html |    1 +
    1 file changed, 1 insertion(+)
    
Isso é um pouco diferente do merge anterior que você fez com a branch hotfix. Neste caso, já que histórico de desenvolvimento divergiu de um ponto mais antigo.

O Git precisa trabalhar um pouco mais, pois o commit na sua branch atual não é um ancestral direto do branch cujas alterações você quer integrar. Neste caso, o Git faz uma simples mesclagem de três vias (three-way merge), usando os dois snapshots referenciados pela ponta de cada branch e o ancestral em comum dos dois.

![image](https://hackmd.io/_uploads/Sy2I0LGXR.png)

Ao invés de apenas mover o ponteiro da branch para a frente, o Git cria um novo snapshot que resulta desse merge em três vias e automaticamente cria um novo commit que aponta para este snapshot. Esse tipo de commit é chamado de commit de merge, e é especial porque tem mais de um pai.

![image](https://hackmd.io/_uploads/SJwPR8fQA.png)

Agora que seu trabalho foi integrado, você não precisa mais da branch iss53. Você pode encerrar o chamado no seu sistema e excluir a branch:

    $ git branch -d iss53
    
Observe que quem trabalhou mais foi o Git, não você, porque os comandos utilizados foram os mesmos.

- Conflitos básicos de mesclagem

De vez em quando, esse processo não acontece de maneira tão tranquila. Se você mudou a mesma parte do mesmo arquivo de maneiras diferentes nas duas branches que você está tentando mesclar, o Git não vai conseguir integrá-las de maneira limpa. Se a sua correção para o problema #53 modificou a mesma parte de um arquivo que também foi modificado em hotfix, você vai ter um conflito de merge que se parece com isso:

    $ git merge iss53
    Auto-merging index.html
    CONFLICT (content): Merge conflict in index.html
    Automatic merge failed; fix conflicts and then commit the result.

O Git não criou automaticamente um novo commit de merge. Ele pausou o processo enquanto você soluciona o conflito. Para ver quais arquivos não foram mesclados a qualquer momento durante um conflito de merge, você pode executar git status:

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

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

        both modified:      index.html

    no changes added to commit (use "git add" and/or "git commit -a")
    
Qualquer arquivo que tenha conflitos que não foram solucionados é listado como unmerged("não mesclado"). O Git adiciona símbolos padrão de resolução de conflitos nos arquivos que têm conflitos, para que você possa abrí-los manualmente e solucionar os conflitos. O seu arquivo contém uma seção que se parece com isso:

    <<<<<<< HEAD:index.html
    <div id="footer">contact : email.support@github.com</div>
    =======
    <div>
     please contact us at support@github.com
    </div>
    >>>>>>> iss53:index.html

Isso significa que a versão em HEAD (a sua branch master, porque era o que estava selecionado quando você executou o comando merge) é a parte superior daquele bloco (tudo após =======), enquanto que a versão na branch iss53 contém a versão na parte de baixo. Para solucionar o conflito, você precisa escolher um dos lados ou mesclar os conteúdos diretamente. Por exemplo, você pode resolver o conflito substituindo o bloco completo por isso:

    <div id="footer">
    please contact us at email.support@github.com
    </div>
    
Essa solução tem um pouco de cada versão, e as linhas com os símbolos <<<<<<<, =======, e >>>>>>> foram completamente removidas. Após solucionar cada uma dessas seções em cada arquivo com conflito, execute `git add` em cada arquivo para marcá-lo como solucionado. Adicionar o arquivo ao stage o marca como resolvido para o Git.

Após você sair da ferramenta, o Git pergunta se a operação foi bem sucedida. Se você responder que sim, o Git adiciona o arquivo ao stage para marcá-lo como resolvido. Você pode executar git status novamente para verificar que todos os conflitos foram resolvidos:

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

    Changes to be committed:

        modified:   index.html

Se você estiver satisfeito e verificar que tudo o que havia conflitos foi testado, você pode digitar git commit para finalizar o commit. A mensagem de confirmação por padrão é semelhante a esta:

    Merge branch 'iss53'

    Conflicts:
        index.html
    #
    # It looks like you may be committing a merge.
    # If this is not correct, please remove the file
    #	.git/MERGE_HEAD
    # and try again.


    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    # On branch master
    # All conflicts fixed but you are still merging.
    #
    # Changes to be committed:
    #	modified:   index.html
    #

Se você acha que seria útil para outras pessoas olhar para este merge no futuro, você pode modificar esta mensagem de confirmação com detalhes sobre como você resolveu o conflito e explicar por que você fez as mudanças que você fez se elas não forem óbvias.

## Rebasing

- O básico do rebase
Se você voltar a um exemplo anterior de Mesclagem Básica, você pode ver que o seu trabalho divergiu e fez commits em duas branches diferentes.

![image](https://hackmd.io/_uploads/SJeWNvMmC.png)

A maneira mais fácil de integrar as branches, como já vimos, é o comando merge. Ele realiza uma fusão de três vias entre os dois últimos snapshots de branch (C3 e C4) e o ancestral comum mais recente dos dois (C2), criando um novo snapshot (e commit).

![image](https://hackmd.io/_uploads/rk3-VPfXA.png)

No entanto, há outra maneira: você pode pegar o patch da mudança que foi introduzida no C4 e reaplicá-lo em cima do C3. No Git, isso é chamado de rebasing. Com o comando rebase, você pode pegar todas as alterações que foram confirmadas em um branch e reproduzi-las em outro.

Neste exemplo, você executaria o seguinte:

    $ git checkout experiment
    $ git rebase master
    First, rewinding head to replay your work on top of it...
    Applying: added staged command

Ele funciona indo para o ancestral comum dos dois branches (aquele em que você está e aquele em que você está fazendo o rebase), obtendo o diff introduzido por cada commit do branch em que você está, salvando esses diffs em arquivos temporários, redefinindo o branch atual para o mesmo commit do branch no qual você está fazendo o rebase e, finalmente, aplicando cada mudança por vez.

::: danger
 Será que precisamos explicar isso? Porque sinceramente nem eu entendi direito
:::

![image](https://hackmd.io/_uploads/r1lS4wfmA.png)

Agora você pode voltar ao branch master e fazer uma fusão rápida.

    $ git checkout master
    $ git merge experiment
    
Agora, o snapshot apontado por C4' é exatamente o mesmo que foi apontado por C5 no exemplo de merge. Não há diferença no produto final da integração, mas o rebase contribui para um histórico mais limpo. Se você examinar o log de um branch que foi feito rebase, parece que todo o trabalho aconteceu em série, mesmo quando originalmente aconteceu em paralelo.

- Rebases mais interessantes

:::danger
Acho que isso talvez seja avançado demais para o escopo e tempo do nosso curso
:::

- Rebase vs. Merge

Existem dois pontos de vista sobre o histórico de commits em um repositório Git. O primeiro considera o histórico de commits como um registro histórico que não deve ser alterado, pois representa o que realmente aconteceu. Mudar o histórico seria como mentir sobre os eventos reais. O segundo ponto de vista vê o histórico de commits como a narrativa de como o projeto foi desenvolvido, e, assim como um rascunho de um livro não é publicado, o histórico deve ser editado para clareza e melhor compreensão futura, utilizando ferramentas como rebase e filter-branch.

A escolha entre merge e rebase não é simples, pois depende das necessidades específicas de cada equipe e projeto. A prática recomendada é fazer rebase em mudanças locais não compartilhadas para manter o histórico limpo, mas nunca faça rebase em algo que você empurrou em algum lugar.
    
## Pull Request e a função de  Review
- O que é o Pull Request?
    É quando solicitámos que a tarefa que fizemos, quando finalizada, seja incrementada no projeto principal.
- Por exemplo, observe a imagem:
![Captura de tela 2024-06-11 163110](https://hackmd.io/_uploads/HkifL7IrA.png)
    > Temos a desenvolvedora Ana que vai trabalhar para um app
    
    > - Este app tem um código principal que está em verde.
    > - Foi criada uma branch para que ana trabalhe e implemente o recurso chat do app
    > - Assim que ela termina todo o chat, ela vai fazer uma solicitação para que o que ela implementou seja margeado, porém sabemos que isso não pode ser feito sem uma revisão, pois podem haver erros.
    > - o Pull request é essa solicitação, que será analisada pelo code Review, que é outro desenvolvedor que tem a atribuição de revisar os códigos.

    
## Fork - Garfar projetos

> Ainda não elaboramos essa parte. Estamos decidindo se vamos ensinar essas funcionalidades do github.
    
    
# Exercícios 

## Exercícios de fixação ($)

### Exercício 1 ($)
   
1. Navegue até a pasta projeto01 que você criou e conectou remotamente.

2. Crie um arquivo aventuras.txt, dentro da pasta onde está o seu reepositório local(projeto01),por enquanto não escreva nada dentro.

3. Faça git status e note que existem mudaças para serem registradas. 

4. Adicione essa mudaça, que é a criação do arquivo historia, na standing área utilizando o comando aprendido.

5. Agora é hora de fazer o commit, digite a seguinte mensagem neste commit "Criei o arquivo historia"

6. Agora escreva o primeiro capítulo, depois adicione ao staging area e faça um commit com a mensagem "adicionei o  capítulo 01".

7. Agora você pode fazer outro capítulo salvar e depois fazer o mesmo processo do passo 6. 
   > Missão: faça 3 capítulos e a cada capítulo faça um commit.

8. Agora é hora de enviar os arquivos e os commits para o repositório remoto. Utilize o comando aprendido.

## Exercícios obrigatórios (#)

### Exercício 1 (#)

1. Crie uma pasta nova em seu computador com o seguinte nome "projeto02"

2. Acesse-a pelo seu terminal utilizando os comando aprendidos no dia anterior.

3. Execute o comando para inicializar o git dentro da pasta/diretório.
    > Dica: este comando cria uma pasta oculta chamada ".git" no diretório

4. Crie um arquivo chamado `biografia<numero de matrícula>.txt` e escreva algumas linhas.
     > Dica: Meu número de matrícula é 20005425 , logo meu arquivo terá o seguinte nome: "biografia20005425.txt"
     > Escrevam algo engraçado, pois a melhor biografia será lida no último dia do nosso minicurso e o vencedor ganhará uma surpresa. 

5. Adicione o arquivo `biografia<numero de matrícula>.txt` ao repositório Git utilizando o comando que coloca as alterações na staging área
    > Dica: antes de fazer o comando, execute git status e analise o que precisa ser trackeado e o que foi modificado.

6. Faça um commit com uma mensagem descritiva dizendo que que você criou o arquivo com a sua biografia.

7. Vá até o arquivo novamente e acrescente seu nome e salve.

8. Adicione a alteração ao repositório Git utilizando o comando que coloca as alterações na staging área.

9. Faça um commit com a seguinte mensagem "coloquei meu nome no arquivo".

8. Digite o comando que visualiza todos os commits feitos e veja o seu histórico de commits.

9. Crie um repositório vazio no github com o nome projeto01
10. Faça o comando para conectar o seu repositório local com o seu repositório remoto criado
11. Depois ulilize o comando que sobe os arquivos do projeto local para o seu repositório remoto.
> Para saber se tudo deu certo, basta olhar os seus commits no repositório do github e analisar se a sua biografia está escrita com o seu nome abaixo.



### Exercício 2 (#)
   
1. Escolha a sua dupla para esta grande aventura.

2. Acesse o GitHub e apenas o componente 'A' deve criar um novo repositório no github com o nome projeto03 e criar um arquivo chamado historia_<numero de matricula de A>_<numero de matricula de A>.txt.

3. Agora ambos têm que clonar o projeto em seus computadores.
   > O aluno B deve pesquisar na barra de pesquisa pelo usuário do aluno A e acessar o repositório criado, para poder clonar.
   
4. Uma vez que ambos clonaram o repositório é hora de criar a história em conjunto.

5. Um dos alunos deve escrever o primeiro capítulo. Vamos chamar o aluno A.
   > Dica: Escrever capítulo > salvar > add > commit > push
6. Agora o aluno B deve atualizar o repositório, puxando as alterações que foram subidas pelo outro aluno para o repositório remoto utilizando o comando aprendido em aula.
   > Assim, antes de o aluno B escrever o capítulo 2, ele vai ter o capitulo 1 no documento já no seu repositório local.

7. Hora do aluno B escrever o próximo capítulo.

8. Agora o aluno A fará o mesmo que o B fez no passo 5 .
   > - Puxar as alterações que foram subidas pelo outro aluno para o repositório remoto
   > - Depois o aluno A terá que escrever o próximo capítulo.

9. Missão: escrever até o capítulo 5.

### Exercicio 3

1. Clone o repositório do projeto <na conta do petcc-exercícios>.

2. Crie uma branch para suas alterações.

3. Vá na pasta onde está o repositório clonado e crie um arquivo chamado "seunome.txt".

4. Adicione o arquivo "<numero da matricula>.txt" ao repositório Git, se o seu número de matrícula é 202343, o arquivo será 202343.txt.

5. Faça um commit com uma mensagem descritiva.
    > Seja criativo! Incremente o arquivo com um texto falando sobre o que achou do curso.
6. Envie suas alterações para o repositório remoto.

7. Crie uma Pull Request pelo github: 
   > 1. Acesse o repositório no GitHub.
   > 2. Navegue até a seção "Pull Requests".
   > 3. Clique no botão "New Pull Request".
   > 4. Selecione sua branch como a branch de origem e a branch principal do projeto como a branch de destino.
   > 5. Adicione um título e uma descrição detalhados para sua Pull Request.
   > 6. Revise as alterações e clique em "Create Pull Request".
   > 8.  Aguarde a revisão da equipe:
   >    > Um membro da equipe revisará suas alterações e poderá solicitar revisões ou aprovar sua Pull Request.
   >    > Responda a quaisquer comentários ou solicitações de revisão e faça as alterações necessárias.

8. Integre suas alterações:
   > Quando sua Pull Request for aprovada, ela poderá ser integrada à branch principal do projeto.
   > O repositório será atualizado com suas alterações e todos os colaboradores poderão acessá-las.

9. Se a sua Pull Request foi aprovada, então parabéns!!! Você conseguiu finalizar o exercício.


