## 🎯 Objetivo Este repositório é um guia de referência para aprender Git e GitLab, desde os primeiros passos até tópicos avançados. Ideal para estudantes, desenvolvedores iniciantes ou quem deseja reforçar conceitos de versionamento de código em projetos individuais ou em equipe. ## Introdução ao git --- O git é um sistema de controle de versão distribuído amplamente utilizado para rastrear mudanças em arquivos de código-fonte durante o desenvolvimento de software. - O Git permite que múltiplos desenvolvedores trabalhem juntos em um projeto, fornecendo ferramentas para colaborar sem sobrescrever o trabalho uns dos outros. - Ele armazena o histórico de versões em um repositório local, permitindo que os usuários revertam para versões anteriores dos arquivos. - Os principais conceitos do git incluem 'commit', 'branch', 'merge', e 'pull request'. ## Configuração inicial do git --- Antes de começar a usar o git, é necessário configurar seu ambiente de usuário. - Instalação do git: Pode ser feita através de gerenciadores de pacotes ou baixando o instalador do site oficial. - Configuração de usuário: Defina seu nome de usuário e endereço de email com os comandos `git config --global user.name "Seu Nome"` e `git config --global user.email "seuemail@exemplo.com"`. - Geração de chave SSH: Para conexões seguras com repositórios remotos, é recomendável gerar uma chave SSH. ## Comandos básicos do git --- O git possui uma série de comandos essenciais para gerenciar repositórios e controlar versões. - `git init`: Inicializa um novo repositório Git local. - `git clone [URL]`: Clona um repositório remoto para o local. - `git add [arquivo]`: Adiciona arquivos à área de preparação (staging area). - `git commit -m "mensagem"`: Grava as mudanças na área de preparação em um novo commit. - `git status`: Mostra o status atual do repositório, incluindo arquivos modificados ou adicionados. ## Trabalhando com branches no git --- Branches são fundamentais no Git para permitir o desenvolvimento paralelo de recursos ou correções. - `git branch [nome]`: Cria uma nova branch. - `git checkout [nome]`: Muda para a branch especificada. - `git merge [nome]`: Mescla as mudanças da branch especificada na branch atual. - Estratégia de branches: É comum usar uma branch 'master' ou 'main' para o código estável e criar branches separadas para desenvolvimento de recursos ou correções. ## Gerenciamento de conflitos no git --- Durante o merge de branches, podem ocorrer conflitos quando as mesmas linhas de código são alteradas de maneiras diferentes. - O Git sinaliza os arquivos com conflitos e o desenvolvedor precisa resolver manualmente. - A resolução de conflitos envolve editar os arquivos para escolher as alterações desejadas e, em seguida, fazer um novo commit. - Ferramentas de merge podem ajudar na visualização e resolução de conflitos. ## Git rebase para histórico linear --- O comando `git rebase` é usado para reescrever o histórico de commits, criando um histórico linear mais limpo. - O rebase move os commits de uma branch para o topo da outra, evitando merges desnecessários. - É útil para atualizar uma branch de recurso com as últimas alterações da branch principal. - Deve ser usado com cautela, pois altera o histórico de commits. ## Trabalhando com repositórios remotos --- Repositórios remotos são versões de seu repositório hospedadas em um servidor, como GitHub ou GitLab. - `git remote add [nome] [URL]`: Adiciona um novo repositório remoto. - `git push [remoto] [branch]`: Envia commits da branch local para a remota. - `git pull [remoto] [branch]`: Atualiza a branch local com as últimas alterações da remota. - É importante manter o repositório local sincronizado com o remoto para evitar conflitos. ## Git stash para salvar mudanças temporárias --- O comando `git stash` é usado para salvar temporariamente alterações não finalizadas, permitindo trocar de branch sem commitar. - `git stash push`: Salva as mudanças atuais em uma pilha temporária. - `git stash list`: Lista todas as entradas na pilha de stashes. - `git stash pop`: Aplica a última entrada da pilha e a remove. - Útil para interromper rapidamente o trabalho atual e mudar para outra tarefa. ## Estratégias de workflow no git --- Existem várias estratégias de workflow no git, como git flow e forking forkflow, que organizam o processo de desenvolvimento. - git flow: Define um modelo estrito com branches específicas para desenvolvimento, recursos, lançamentos e correções. - forking workflow: Cada desenvolvedor tem seu próprio repositório, e as contribuições são feitas através de pull requests. - Escolher uma estratégia de workflow depende das necessidades da equipe e do projeto. ## Git cherry-pick para aplicar commits específicos --- O comando `git cherry-pick` permite aplicar as mudanças de commits específicos de uma branch para outra. - Útil para trazer correções ou recursos específicos para outra branch sem fazer um merge completo. - Use `git cherry-pick [commit]` para aplicar as mudanças do commit especificado. - Pode causar conflitos se as mudanças não se aplicarem limpa na branch de destino. ## Reflog do git para recuperação de dados --- O reflog do Git registra as atualizações feitas nas referências dos repositórios, como branches e tags, facilitando a recuperação de dados perdidos. - Use `git reflog` para exibir o histórico de alterações nas referências. - Cada entrada mostra a ação realizada (como um commit ou um checkout) e o hash do commit. - Para recuperar um estado anterior, use `git reset --hard [reflog entry]`. - O reflog é uma ferramenta de segurança, pois permite reverter ações acidentais, como redefinições ou rebase. ## Git clean para remover arquivos não rastreados --- O comando `git clean` é usado para remover arquivos não rastreados do diretório de trabalho, ajudando a manter o repositório limpo. - Use `git clean -n` para fazer uma simulação e mostrar quais arquivos seriam removidos. - `git clean -f` remove os arquivos não rastreados. - `git clean -fd` remove também os diretórios não rastreados. - Use com cautela, pois essa ação é irreversível e pode resultar na perda de dados não rastreados. ## Tags no git para versões de lançamento --- As tags no Git são usadas para marcar pontos específicos no histórico do repositório, como versões de lançamento. - Use `git tag [nome]` para criar uma tag leve apontando para o commit atual. - Para uma tag anotada, que inclui informações adicionais como autor e data, use `git tag -a [nome] -m "mensagem"`. - As tags podem ser enviadas para repositórios remotos com `git push --tags`. - Elas são úteis para marcar versões estáveis do software ou pontos de referência importantes no desenvolvimento. ## Git revert para desfazer commits --- O comando `git revert` cria um novo commit que desfaz as mudanças de um commit anterior, preservando o histórico. - Use `git revert [commit]` para gerar um commit que inverte as alterações do commit especificado. - Diferente do `git reset`, o revert não altera o histórico existente, tornando-o seguro para repositórios compartilhados. - Pode ser usado para desfazer alterações indesejadas ou erros sem reescrever o histórico de commits. ## Git ignore para excluir arquivos do controle de versão --- O arquivo `.gitignore` é usado para especificar arquivos ou diretórios que devem ser ignorados pelo Git, evitando que sejam rastreados. - Crie um arquivo chamado `.gitignore` no diretório raiz do repositório. - Adicione padrões de arquivo ou diretório que devem ser ignorados (por exemplo, `*.log`, `build/`). - Arquivos ignorados não aparecerão em `git status` e não serão adicionados ao repositório. - Útil para excluir arquivos temporários, de compilação ou sensíveis do controle de versão. # Entendendo a Relação entre Repositório Fonte e Cópia Sincronizada (fork) Já imaginou como manter seu fork atualizado com as mudanças do projeto original? A chave está na configuração inteligente dos repositórios remotos! ![[2025-03-18_15h22_34.png]] ## 🔄 Os Três Pilares do Versionamento ## 1. Repositório Fonte (Primário) - **Função**: Base oficial do projeto, geralmente mantido pelo autor original - **Identificação no Git**: Nomeado como `upstream` (referência à origem do fluxo) - **Característica**: Somente leitura para contribuidores externos ## 2. Cópia Pessoal (Derivado) - **Origem**: Criado através do botão "Fork" na interface do GitLab/GitHub - **Identificação no Git**: Chamado de `origin` após clonagem - **Vantagem**: Seu espaço seguro para experimentações ## 3. Ambiente Local - **Finalidade**: Máquina física onde o desenvolvimento acontece - **Gestão**: Conexão simultânea com `origin` e `upstream` ## ⚙️ Configuração Estratégica de Remotos 1. **Clonagem do Derivado** Obtenha sua cópia pessoal: ```bash git clone git@gitlab.com:seu_usuario/cblc.git cd cblc ``` 2. **Vinculação com o fonte** ```bash git remote add upstream https://gitlab.com/blau_araujo/cblc.git ``` 3. **Verificação de Conexões** ```bash git remote -v # origin git@gitlab.com:seu_usuario/cblc.git (push/fetch) # upstream https://gitlab.com/blau_araujo/cblc.git (push/fetch) ``` ## 💡 Por Que Esta Estrutura? - **Sincronização Simplificada**: Atualize seu fork com `git fetch upstream` - **Controle de Versão**: Mantenha histórico limpo entre suas alterações e as oficiais - **Colaboração Eficiente**: Envie alterações via `origin` sem afetar o projeto principal > **Dica Pro**: Use `upstream` para puxar atualizações e `origin` para enviar suas contribuições! ## 🔍 Fluxo de Atualização Básico ```bash # Obter mudanças do projeto original git fetch upstream main # Mesclar com sua cópia local git merge upstream/main # Atualizar fork remoto git push origin main ``` Esta estrutura garante que seu ambiente sempre reflita as mudanças mais recentes do projeto, enquanto mantém suas contribuições isoladas e organizadas. # **Workflow Recomendado para acompanhar o curso** ## 1. **Sincronize o `main` do seu fork com o repositório do professor** Sempre que o professor atualizar o `upstream/main`, atualize seu fork: ```bash git checkout main git fetch upstream main # Puxa as atualizações do professor git reset --hard upstream/main # Alinha seu main local com o upstream git push origin main --force # Atualiza seu fork no GitHub (origin) ``` ## 2. **Crie um branch para cada exercício** Nunca trabalhe diretamente no `main`. Para cada novo exercício: ```bash git checkout main git checkout -b exercicio-1 # Cria um branch a partir do main atualizado ``` ## 3. **Desenvolva no branch do exercício** Faça commits normalmente: ```bash git add . git commit -m "Resolução do exercício 1" ``` ## 4. **Atualize o branch do exercício com as mudanças do professor** Se o professor atualizar o `upstream/main` enquanto você está trabalhando: ```bash git checkout main git fetch upstream main git reset --hard upstream/main git push origin main --force git checkout exercicio-1 git rebase main # Atualiza seu branch com as mudanças do professor ``` - Se houver conflitos, resolva-os durante o rebase. ## **Por que o `git reset --hard upstream/main`?** Quando você faz um fork de um projeto, seu repositório (`origin`) começa como uma cópia exata do projeto original (`upstream`). Com o tempo, o `upstream/main` (o branch principal do projeto original) pode ser atualizado com novos commits, enquanto seu fork (`origin/main`) pode ficar desatualizado ou acumular commits próprios. O comando **`git reset --hard upstream/main`** serve para: 1. **Forçar seu branch local `main` a corresponder exatamente ao `upstream/main`**. 2. **Descartar quaisquer commits locais ou alterações que não existam no `upstream`**. 3. **Garantir que seu fork volte a ser um espelho perfeito do repositório original**. --- ### **Quando isso é útil?** - Você fez commits acidentais no `main` do seu fork (em vez de usar branches). - O `upstream/main` foi atualizado, e você quer sincronizar seu fork **descartando alterações locais**. - Você quer "limpar" o histórico do seu fork para evitar conflitos futuros. Em resumo: desde que seus branches não estejam diretamente ligados ao `main` (ou você tenha backups), o `git reset --hard` não os afeta! 😊 ## 5. **Envie o branch para seu fork (GitHub)** ```bash git push origin exercicio-1 ``` --- ### **Fluxo Visual** ```txt main (origin/main) → sempre igual ao upstream/main (professor) / upstream/main \ exercicio-1 → seu branch de trabalho ``` --- ## **Por que essa recomendação?** - **`main` limpo**: Sempre reflete o estado oficial do professor. - **Branches isolados**: Cada exercício tem seu próprio histórico, sem interferir no `main`. - **Atualizações seguras**: O `git rebase main` mantém seu branch atualizado com as mudanças do professor. --- ## **Quando NÃO usar `git reset --hard`?** - Se você tem commits locais **que quer manter**. - Se outros colaboradores dependem do histórico do seu fork. - **Solução alternativa**: Crie um branch novo para seus commits e sincronize o `main` sem perder trabalho ## **Dicas Importantes** 1. **Nunca commite no `main`**: Isso evitará divergências com o `upstream`. 2. **Use `git fetch` antes de trabalhar**: Verifique se há atualizações do professor. 3. **Nomeie branches claramente**: Ex: `exercicio-1`, `projeto-final`, etc. 4. **Apague branches antigos** após a correção: ```bash git branch -D exercicio-1 # Local git push origin --delete exercicio-1 # Remoto ``` --- ## **Se o Professor Pedir para Entregar o Exercício** 1. Envie o branch para seu fork (`git push origin exercicio-1`). 2. Abra um **Pull Request** no repositório do professor (se for o processo definido por ele). 3. Ou compartilhe o link do branch no seu fork (ex: `https://github.com/seu-user/seu-fork/tree/exercicio-1`). ### **Benefícios** - Você mantém um histórico organizado. - O `main` do seu fork sempre estará pronto para receber novas atualizações do professor. - Seus exercícios ficam isolados e fáceis de gerenciar. Esse workflow é amplamente usado em projetos open source e ambientes educacionais! 🚀