diff --git a/3-comandos/branch.md b/3-comandos/branch.md index eb51eb3..8e2766f 100755 --- a/3-comandos/branch.md +++ b/3-comandos/branch.md @@ -3,23 +3,25 @@ Simplificado: _Universo Paralelo_

Podemos dizer que a branch é um universo ou uma realidade alternativa onde em algum ponto irá se juntar com a realidade principal. Achou esse exemplo estranho? Então deixa eu te mostrar uns exemplos.

Pense em um cenário onde seu time encontra um problema que precisa ser resolvido, porém nem sempre há apenas uma única solução para finalizar essa tarefa, certo? É ai que a branch entra para ajudar nessa organização entre os devs.
-Continuando nesse cenário hipotético, os desenvolvedores irão criar uma nova vertente do código partindo da branch **master** (branch principal gerada a partir do primeiro commit), assim criando a branch implementacao-css. +Continuando nesse cenário hipotético, os desenvolvedores irão criar uma nova vertente do código partindo da branch **main** (branch principal gerada a partir do primeiro commit; em projetos mais antigos você pode encontrar o nome **master** com o mesmo papel), assim criando a branch implementacao-css. A tarefa hipotética é: implementar uma regra CSS especifica na nossa index.html. -Porém, antes precisamos criar uma nova branch e para isso iremos usar o comando **git checkout** com o primeiro argumento **-b (branch)** e o segundo sendo o nome da nova branch. +Porém, antes precisamos criar uma nova branch e para isso iremos usar o comando **git switch** com a flag **-c (create)** seguida do nome da nova branch. ``` -$ git checkout -b implementacao-css +$ git switch -c implementacao-css Switched to a new branch 'implementacao-css' $ git branch - master + main * implementacao-css ``` +> Em versões mais antigas do Git (ou em tutoriais antigos) você verá o comando equivalente `git checkout -b implementacao-css`. Ele funciona da mesma forma, mas `git switch` foi criado para deixar mais claro que a intenção é apenas trocar de branch (o `checkout` acumula muitas outras funções e pode confundir quem está começando). + ![x](/images/branches1.png) -Podemos ver que agora estamos em um outro universo diferente do principal (master) e toda e qualquer alteração feita nessa nova branch não afetará nenhuma outra dentro do projeto.

+Podemos ver que agora estamos em um outro universo diferente do principal (main) e toda e qualquer alteração feita nessa nova branch não afetará nenhuma outra dentro do projeto.

Tá, mas o que eu faço com essa branch? A ideia é você ter liberdade para criar coisas novas sem alterar onde está tudo funcionando (master).
Vamos fazer algumas alterações no nosso projeto dentro dessa nova branch: diff --git a/3-comandos/cherry-pick.md b/3-comandos/cherry-pick.md index 5c0fc42..4663631 100644 --- a/3-comandos/cherry-pick.md +++ b/3-comandos/cherry-pick.md @@ -132,3 +132,5 @@ O comando `cherry-pick` pode ser usado em conjunto com outros comandos, conhecid Sim, existem várias possibilidades de uso do comando `cherry-pick`. Você pode ver mais detalhes sobre o comando `cherry-pick` na [documentação oficial](https://git-scm.com/docs/git-cherry-pick/pt_BR). +Ir para: [4.1 Gitflow - O que é Git Flow](../4-gitflow/o-que-e-gitflow.md) + diff --git a/3-comandos/clone.md b/3-comandos/clone.md new file mode 100644 index 0000000..e46fd0f --- /dev/null +++ b/3-comandos/clone.md @@ -0,0 +1,38 @@ +# Clone + +Simplificado: _Baixar uma cópia completa de um repositório_

+Até agora vimos o `git init`, que cria um repositório **novo e vazio**. Mas no dia a dia, o mais comum é você entrar em um projeto que **já existe** - seja no trabalho, em um projeto open source, ou em um repositório que você acabou de dar fork no GitHub. + +Para isso usamos o comando **git clone**, passando a URL do repositório: + +```bash +git clone https://github.com/usuario/nome-do-repositorio.git +``` + +Isso vai: + +1. Criar uma pasta com o nome do repositório; +2. Baixar todo o histórico de commits, branches e tags; +3. Configurar automaticamente o repositório remoto chamado `origin`, apontando para a URL clonada (veremos mais sobre isso em [Remote](remote.md)). + +Se quiser clonar em uma pasta com outro nome: + +```bash +git clone https://github.com/usuario/nome-do-repositorio.git meu-projeto +``` + +## HTTPS vs SSH + +Você vai notar que o GitHub oferece duas URLs para clonar: + +```bash +# HTTPS - pede usuário/token (ou abre o navegador) ao fazer push +git clone https://github.com/usuario/nome-do-repositorio.git + +# SSH - usa uma chave configurada na sua máquina, sem pedir senha depois +git clone git@github.com:usuario/nome-do-repositorio.git +``` + +No começo, HTTPS costuma ser mais simples. Conforme você for fazer `push` com frequência, vale configurar uma chave SSH para não precisar autenticar a cada envio. + +Ir para: [3.2. Config](config.md) diff --git a/3-comandos/config.md b/3-comandos/config.md index 7b0e602..c5dc3b6 100644 --- a/3-comandos/config.md +++ b/3-comandos/config.md @@ -17,4 +17,4 @@ Listando todas as configurações existentes: git config --list ``` -Ir para: [3.3. Commit](commit.md) \ No newline at end of file +Ir para: [3.3. .gitignore](gitignore.md) \ No newline at end of file diff --git a/3-comandos/gitignore.md b/3-comandos/gitignore.md new file mode 100644 index 0000000..1f0a57b --- /dev/null +++ b/3-comandos/gitignore.md @@ -0,0 +1,49 @@ +# .gitignore + +Simplificado: _Lista de "não me siga"_

+Todo projeto tem arquivos que **não devem** ir para o repositório: senhas, chaves de API, pastas de dependências (`node_modules`, `vendor`), arquivos de build, configurações pessoais do seu editor, logs, etc. + +Se você rodar um `git add .` sem cuidado, todos esses arquivos entram no commit e acabam no histórico do projeto - inclusive em repositórios públicos no GitHub, o que pode expor senhas e chaves de acesso. + +Para evitar isso, criamos um arquivo chamado **.gitignore** na raiz do projeto, listando o que o Git deve ignorar. + +``` +$ touch .gitignore +``` + +Dentro dele, cada linha representa um padrão de arquivo ou pasta a ser ignorado: + +```gitignore +# Dependências +node_modules/ +vendor/ + +# Variáveis de ambiente e segredos +.env +.env.* +*.pem + +# Build +dist/ +build/ + +# Logs +*.log + +# Configurações do editor/IDE +.vscode/ +.idea/ +``` + +## Pontos importantes + +- O `.gitignore` só funciona para arquivos **ainda não rastreados** pelo Git. Se um arquivo já foi commitado antes de entrar no `.gitignore`, ele continuará sendo monitorado - é necessário remover do controle de versão com: + +```bash +git rm --cached caminho/do/arquivo +``` + +- Existem modelos prontos de `.gitignore` para praticamente toda linguagem/framework no site [gitignore.io](https://www.toptal.com/developers/gitignore) ou no repositório oficial [github/gitignore](https://github.com/github/gitignore). +- **Nunca** suba arquivos `.env`, credenciais, tokens ou chaves privadas para o repositório, mesmo que ele seja privado. + +Ir para: [3.5. Commit](commit.md) diff --git a/3-comandos/log.md b/3-comandos/log.md index 6285725..7de0513 100644 --- a/3-comandos/log.md +++ b/3-comandos/log.md @@ -48,4 +48,4 @@ exibir o histórico de uma arquivo em especifico git log -- ``` -Ir para: [4.1 Gitflow - O que é Git Flow](../4-gitflow/o-que-e-gitflow.md) \ No newline at end of file +Ir para: [3.17. Stash](stash.md) \ No newline at end of file diff --git a/3-comandos/merge.md b/3-comandos/merge.md index ed83716..85ebfd3 100755 --- a/3-comandos/merge.md +++ b/3-comandos/merge.md @@ -2,10 +2,10 @@ Simplificado: _Fusão de duas branches_

Quando algum desenvolvedor falar de **merge**, quer dizer que houve uma fusão ou junção de códigos em uma única branch. Tá, mas como assim?
-Vamos continuar na nossa situação hipotética dos commits acima, já que temos duas branches nesse repositório. Iremos criar um merge da branch **implementacao-css** para a branch **master**. Em outras palavras, vamos juntar todas as alterações feitas na branch **implementacao-css** dentro da branch **master**, mantendo a nossa master com todo o conteúdo. +Vamos continuar na nossa situação hipotética dos commits acima, já que temos duas branches nesse repositório. Iremos criar um merge da branch **implementacao-css** para a branch **main**. Em outras palavras, vamos juntar todas as alterações feitas na branch **implementacao-css** dentro da branch **main**, mantendo a nossa main com todo o conteúdo. ``` -$ git checkout master +$ git switch main $ git merge implementacao-css Updating 9b61048..ab4a625 Fast-forward @@ -16,6 +16,10 @@ Fast-forward ![imagem listando as branches](/images/merge1.png) -Podemos ver que a master agora possui as funcionalidades da implementação-css sem precisar mexer em nada relacionado a ela, e em questão de organização você sabe onde e quando foi feito as alterações. +Podemos ver que a main agora possui as funcionalidades da implementação-css sem precisar mexer em nada relacionado a ela, e em questão de organização você sabe onde e quando foi feito as alterações. + +## E se houver conflito? + +No exemplo acima o Git conseguiu juntar tudo automaticamente (fast-forward) porque a **main** não tinha recebido nenhum commit novo desde que a branch **implementacao-css** foi criada. Mas se as duas branches alterarem a **mesma linha do mesmo arquivo**, o Git não vai saber qual versão manter e vai te avisar de um **conflito de merge**. Esse é exatamente o tipo de situação que costuma assustar quem está começando — e tem um capítulo dedicado a isso em [Resolvendo conflitos](../5-github/resolvendo-conflitos.md). Ir para: [3.6. Status](status.md) \ No newline at end of file diff --git a/3-comandos/pull.md b/3-comandos/pull.md new file mode 100644 index 0000000..92259e9 --- /dev/null +++ b/3-comandos/pull.md @@ -0,0 +1,39 @@ +# Pull + +Simplificado: _Trazer as novidades do remote para o seu projeto local_

+Enquanto você trabalha, seus colegas também estão commitando e fazendo `push` de alterações. O comando `git pull` serve para **atualizar sua branch local** com tudo que já foi enviado ao remote. + +```bash +git pull origin main +``` + +Na prática, `git pull` é a combinação de dois comandos que você já conhece: + +```bash +git fetch origin # baixa as novidades do remote (sem alterar seus arquivos) +git merge origin/main # mescla essas novidades na sua branch atual +``` + +Veja [Fetch](fetch.md) para entender melhor a primeira parte. + +## Quando rodar `git pull`? + +- **Antes de começar a trabalhar**, para garantir que você está partindo do código mais atualizado; +- **Antes de criar uma branch nova**, para que ela já nasça a partir da versão mais recente da `main`; +- **Antes de dar `git push`**, caso o remote tenha recebido alterações novas desde a última vez que você sincronizou (veja [Push](push.md)). + +## Pull pode gerar conflitos + +Como o `pull` faz um `merge` por debaixo dos panos, se você e um colega alteraram a **mesma linha do mesmo arquivo**, o Git vai pedir para você resolver o conflito manualmente antes de continuar. Isso é normal e faz parte do trabalho em equipe - veja o passo a passo em [Resolvendo conflitos](../5-github/resolvendo-conflitos.md). + +## git pull --rebase + +Uma alternativa ao merge automático do `pull` é pedir para o Git **reaplicar seus commits locais por cima** das novidades baixadas, mantendo o histórico mais linear (sem um commit de merge extra): + +```bash +git pull --rebase origin main +``` + +Útil em times que preferem um histórico de commits mais "limpo", mas exige mais atenção ao resolver conflitos (veja [Rebase](rebase.md)). + +Ir para: [3.15. Fetch](fetch.md) diff --git a/3-comandos/push.md b/3-comandos/push.md new file mode 100644 index 0000000..8b7d92e --- /dev/null +++ b/3-comandos/push.md @@ -0,0 +1,47 @@ +# Push + +Simplificado: _Enviar seus commits para o repositório remoto_

+Tudo que você faz com `git commit` fica guardado **localmente**, na sua máquina. Para que seu time (ou o GitHub) veja essas alterações, você precisa **enviá-las** para o remote com o comando `git push`. + +```bash +git push origin main +``` + +Isso envia os commits da sua branch `main` local para a branch `main` do remote `origin`. + +## Primeiro push de uma branch nova + +Quando você cria uma branch nova localmente (com `git switch -c minha-feature`) e faz commits nela, essa branch ainda **não existe** no remote. No primeiro push, use `-u` (ou `--set-upstream`) para vincular sua branch local à branch remota: + +```bash +git push -u origin minha-feature +``` + +A partir daí, basta `git push` (sem mais nada) que o Git já sabe para onde enviar. + +## Erros comuns + +### "rejected... (fetch first)" / "non-fast-forward" + +``` +! [rejected] main -> main (fetch first) +error: failed to push some refs +``` + +Isso significa que o remote tem commits que você ainda não tem localmente (alguém do time fez push antes de você). A solução **não é forçar o push**, e sim trazer as alterações primeiro: + +```bash +git pull +# resolva eventuais conflitos (veja resolvendo-conflitos.md) +git push +``` + +### Nunca use `git push --force` em branches compartilhadas + +```bash +git push --force origin main +``` + +Esse comando **sobrescreve o histórico remoto**, podendo apagar commits dos seus colegas sem aviso. Use apenas em branches pessoais (ex: sua própria branch de feature, antes de abrir o Pull Request) e, mesmo assim, prefira `git push --force-with-lease`, que falha caso alguém tenha enviado algo novo que você ainda não viu. + +Ir para: [3.14. Pull](pull.md) diff --git a/3-comandos/remote.md b/3-comandos/remote.md new file mode 100644 index 0000000..a22e802 --- /dev/null +++ b/3-comandos/remote.md @@ -0,0 +1,50 @@ +# Remote + +Simplificado: _O "endereço" do repositório na nuvem_

+Tudo que vimos até agora aconteceu **apenas na sua máquina**. Mas o Git é um sistema distribuído: o mesmo repositório pode existir em vários lugares - na sua máquina, na do seu colega, e em um servidor compartilhado como GitHub, GitLab ou Bitbucket. + +Um **remote** é justamente uma referência para uma dessas outras cópias do repositório. Quando você clona um projeto (veja [Clone](clone.md)), o Git já cria automaticamente um remote chamado `origin`, apontando para a URL de onde você clonou. + +## Listando os remotes configurados + +```bash +$ git remote -v +origin https://github.com/usuario/nome-do-repositorio.git (fetch) +origin https://github.com/usuario/nome-do-repositorio.git (push) +``` + +## Adicionando um novo remote + +Útil quando você criou o repositório localmente com `git init` e agora quer conectá-lo a um repositório vazio criado no GitHub: + +```bash +git remote add origin https://github.com/usuario/nome-do-repositorio.git +``` + +## Trabalhando com forks: origin vs upstream + +Uma situação muito comum em times e em projetos open source: você faz um **fork** (sua cópia) de um repositório, clona o **seu fork**, mas também precisa acompanhar as atualizações do repositório **original**. Para isso, é comum adicionar um segundo remote chamado `upstream`: + +```bash +$ git remote -v +origin https://github.com/seu-usuario/projeto.git (fetch) +origin https://github.com/seu-usuario/projeto.git (push) + +$ git remote add upstream https://github.com/dono-original/projeto.git +$ git remote -v +origin https://github.com/seu-usuario/projeto.git (fetch) +origin https://github.com/seu-usuario/projeto.git (push) +upstream https://github.com/dono-original/projeto.git (fetch) +upstream https://github.com/dono-original/projeto.git (push) +``` + +Assim você pode usar `git fetch upstream` / `git merge upstream/main` para trazer as novidades do projeto original para o seu fork, sem perder a referência de onde enviar (`push`) as suas próprias alterações (`origin`). Esse fluxo é detalhado em [Fork e Pull Request](../5-github/fork-e-pull-request.md). + +## Removendo ou renomeando um remote + +```bash +git remote remove upstream +git remote rename origin upstream +``` + +Ir para: [3.13. Push](push.md) diff --git a/3-comandos/repositorio.md b/3-comandos/repositorio.md index 36a6d98..6af885c 100755 --- a/3-comandos/repositorio.md +++ b/3-comandos/repositorio.md @@ -13,4 +13,4 @@ Initialized empty Git repository in ~/git4noobs/.git/ Simples, não é mesmo?! -Ir para: [3.2. Config](config.md) \ No newline at end of file +Ir para: [3.1.1. Clone](clone.md), uma forma alternativa de iniciar um repositório a partir de um projeto já existente, ou direto para [3.2. Config](config.md) \ No newline at end of file diff --git a/3-comandos/reset.md b/3-comandos/reset.md index 1d02f36..6d02489 100644 --- a/3-comandos/reset.md +++ b/3-comandos/reset.md @@ -20,4 +20,4 @@ Com o `--soft` podemos voltar para uma hash de um commit mantendo os arquivos ed git reset --soft d60329e ``` -Ir para: [3.11. Fetch](../3-comandos/fetch.md) +Ir para: [3.12. Remote](remote.md) diff --git a/3-comandos/stash.md b/3-comandos/stash.md index c178fb7..d821b37 100644 --- a/3-comandos/stash.md +++ b/3-comandos/stash.md @@ -137,4 +137,6 @@ Vamos testar na pratica ainda com a pasta que você criou: O comando `git stash` pode ser útil em varios casos diversos e definitivamente é uma comando poderoso para se ter ciência, vale a pena conferir na [documentação](https://git-scm.com/docs/git-stash) -para aprender mais sobre esse comando. \ No newline at end of file +para aprender mais sobre esse comando. + +Ir para: [3.18. Cherry-pick](cherry-pick.md) \ No newline at end of file diff --git a/3-comandos/status.md b/3-comandos/status.md index 10b8e3b..7575ecd 100755 --- a/3-comandos/status.md +++ b/3-comandos/status.md @@ -4,7 +4,7 @@ Um comando simples para saber qual branch você se encontra, quais arquivos fora ``` $ git status -No ramo master +No ramo main Mudanças a serem submetidas: (use "git reset HEAD ..." to unstage) modified: main.css diff --git a/3-comandos/tag.md b/3-comandos/tag.md index 6473945..41ce19e 100755 --- a/3-comandos/tag.md +++ b/3-comandos/tag.md @@ -11,23 +11,23 @@ O formato padrão para uma tag é Vx.y.z, sendo: ## Opções -### Gerar tag non-annontated +### Gerar tag lightweight (non-annotated) ```sh git tag v1.0.0 ``` -Cria uma tag `non-annontated` **possui** referencia direta ao commmit que ela foi gerada. +Cria uma tag `lightweight`, que é apenas um **ponteiro/referência direta** para o commit atual, sem nenhuma informação extra (sem autor, data ou mensagem própria). --- ### Gerar tag annotated ```sh -git tag -a v1.0.0 +git tag -a v1.0.0 -m "Versão 1.0.0" ``` -Cria uma tag `annotated` **não possui** referencia direta ao commmit que ela foi gerada, possuindo uma mensagem propria. +Cria uma tag `annotated`, que também aponta para o commit, mas é armazenada como um objeto completo no Git, guardando **mensagem própria, autor e data**. Por isso é a forma recomendada para marcar versões/releases. --- diff --git a/4-gitflow/padrao-commit.md b/4-gitflow/padrao-commit.md index 9f81c0c..34f4bad 100755 --- a/4-gitflow/padrao-commit.md +++ b/4-gitflow/padrao-commit.md @@ -34,4 +34,4 @@ No exemplo abaixo iremos separar o back-end do front-end para entender como melh Em vez de fazer um único commit com vários arquivos indicando uma única task, você pode fazer algo mais elaborado pra conseguir identificar melhor o que foi está sendo feito. -Ir para: [Conclusão](../conclusao.md) \ No newline at end of file +Ir para: [5.1 GitHub - O que é o GitHub?](../5-github/o-que-e-github.md) \ No newline at end of file diff --git a/5-github/code-review.md b/5-github/code-review.md new file mode 100644 index 0000000..be23e44 --- /dev/null +++ b/5-github/code-review.md @@ -0,0 +1,53 @@ +# Code Review + +Simplificado: _Um colega lê seu código antes dele entrar no projeto_

+Code review é a etapa em que outra pessoa do time analisa as alterações de um Pull Request antes de aprová-lo. O objetivo não é "achar erro de quem escreveu", mas sim: + +- Pegar bugs e casos esquecidos antes de chegarem em produção; +- Manter um padrão de código consistente no projeto; +- Compartilhar conhecimento - todo mundo entende um pouco do que está sendo feito; +- Ter um segundo olhar antes de mudanças irreversíveis (ex: alterações em banco de dados). + +## Como funciona no GitHub + +Na aba **"Files changed"** de um Pull Request, qualquer revisor pode: + +- Comentar em uma linha específica do código; +- Sugerir uma alteração de código diretamente (`Suggest change`), que o autor pode aceitar com um clique; +- Marcar a revisão como: + - **Comment**: apenas comentários, sem bloquear o PR; + - **Approve**: aprova as alterações - dependendo das regras do repositório, isso libera o merge; + - **Request changes**: pede ajustes antes de aprovar - o autor faz novos commits/push na mesma branch e o PR atualiza. + +## Dando feedback (como revisor) + +- Seja específico: "essa função pode lançar erro se `lista` vier vazia, já tratamos isso?" é mais útil que "ajustar tratamento de erro"; +- Separe o que é **bloqueante** (precisa mudar antes do merge) do que é **sugestão/opinião** - muitos times usam prefixos como `nit:` (nitpick, não bloqueante) para isso; +- Elogie o que está bom também - review não é só apontar problema. + +## Recebendo feedback (como autor) + +- Não é pessoal - o objetivo é o código ficar melhor; +- Se não concordar com um comentário, explique seu raciocínio em vez de simplesmente ignorar ou aceitar sem entender; +- Depois de ajustar, responda os comentários (o GitHub permite marcar como "resolved") e dê push - o PR atualiza automaticamente. + +## Fazendo merge do Pull Request + +Depois de aprovado (e com os conflitos resolvidos, veja [Resolvendo conflitos](resolvendo-conflitos.md)), o GitHub oferece três formas de integrar o PR na branch principal: + +- **Create a merge commit**: mantém todos os commits da branch + cria um commit de merge. Histórico completo, porém mais "poluído"; +- **Squash and merge**: junta todos os commits do PR em **um único commit** na `main`. Histórico mais limpo, ótimo quando a branch tem muitos commits de "WIP", "ajuste", "fix typo"; +- **Rebase and merge**: reaplica os commits da branch sobre a `main`, sem criar commit de merge. Mantém histórico linear, mas reescreve os hashes dos commits. + +A escolha costuma ser **uma convenção do time** (geralmente combinada com a estratégia de [GitFlow](../4-gitflow/o-que-e-gitflow.md) adotada no projeto) - o importante é manter consistência. + +Depois do merge, é seguro apagar a branch (o próprio GitHub oferece o botão "Delete branch"): + +```bash +git switch main +git pull +git branch -d feature/cadastro-de-clientes # apaga local +git push origin --delete feature/cadastro-de-clientes # apaga remota (se ainda existir) +``` + +Ir para: [Conclusão](../conclusao.md) diff --git a/5-github/fork-e-pull-request.md b/5-github/fork-e-pull-request.md new file mode 100644 index 0000000..8a055b9 --- /dev/null +++ b/5-github/fork-e-pull-request.md @@ -0,0 +1,73 @@ +# Fork e Pull Request + +Simplificado: _A forma organizada de propor mudanças em um projeto_

+Esse é provavelmente o fluxo mais importante para trabalhar em equipe no GitHub. A ideia central é: **ninguém commita direto na branch principal (`main`)**. Toda alteração passa por uma branch própria e por uma revisão antes de ser integrada. + +## Cenário 1: você tem acesso de escrita ao repositório + +```bash +# 1. Atualize sua main local +git switch main +git pull + +# 2. Crie uma branch para a sua tarefa +git switch -c feature/cadastro-de-clientes + +# 3. Trabalhe normalmente: edite, adicione, commite +git add . +git commit -m "Adiciona formulário de cadastro de clientes" + +# 4. Envie sua branch para o GitHub +git push -u origin feature/cadastro-de-clientes +``` + +Depois do push, o GitHub mostra um botão **"Compare & pull request"**. Ao clicar: + +1. Escolha a branch de destino (geralmente `main`) e a branch de origem (`feature/cadastro-de-clientes`); +2. Escreva um título e uma descrição explicando **o que** foi feito e **por quê** - isso ajuda quem for revisar; +3. Adicione revisores (colegas de time); +4. Clique em **Create pull request**. + +A partir daí, qualquer novo `git push` na mesma branch atualiza automaticamente o Pull Request (PR). + +## Cenário 2: Fork (você não tem acesso de escrita) + +Muito comum em projetos open source ou ao contribuir com um repositório de outra organização (foi exatamente assim que este material chegou até você: via fork 🙂). + +```bash +# 1. No GitHub, clique em "Fork" no repositório original. +# Isso cria uma cópia em https://github.com/SEU_USUARIO/projeto + +# 2. Clone o SEU fork (não o original) +git clone https://github.com/SEU_USUARIO/projeto.git +cd projeto + +# 3. Adicione o repositório original como "upstream" +git remote add upstream https://github.com/dono-original/projeto.git + +# 4. Crie sua branch, trabalhe e suba para o SEU fork (origin) +git switch -c feature/melhoria-na-documentacao +git add . +git commit -m "Adiciona seção sobre GitHub" +git push -u origin feature/melhoria-na-documentacao +``` + +5. No GitHub, abra o Pull Request do seu fork (`SEU_USUARIO/projeto:feature/melhoria-na-documentacao`) para o repositório original (`dono-original/projeto:main`). + +Para manter seu fork atualizado com o projeto original ao longo do tempo: + +```bash +git switch main +git fetch upstream +git merge upstream/main +git push origin main +``` + +## Boas práticas de branch e PR + +- **Nomes de branch descritivos**: `feature/...`, `fix/...`, `hotfix/...`, `docs/...` - facilita identificar o objetivo só pelo nome (veja também [GitFlow](../4-gitflow/o-que-e-gitflow.md)); +- **PRs pequenos e focados**: um PR que faz "uma coisa" é muito mais fácil (e rápido) de revisar do que um PR gigante que mistura várias alterações; +- **Descreva o "porquê"**, não só o "o quê" - o código já mostra o que mudou, a descrição do PR explica o motivo; +- **Não force push em branches que outros já estão revisando** sem avisar - isso pode reescrever o histórico que o revisor já viu (veja [Push](../3-comandos/push.md)). + +Ir para: [5.3. Resolvendo conflitos](resolvendo-conflitos.md) diff --git a/5-github/o-que-e-github.md b/5-github/o-que-e-github.md new file mode 100644 index 0000000..54446e2 --- /dev/null +++ b/5-github/o-que-e-github.md @@ -0,0 +1,33 @@ +# O que é o GitHub? + +Simplificado: _A rede social dos repositórios Git_

+Até aqui falamos só do **Git**: a ferramenta que roda na sua máquina e versiona seus arquivos. O **GitHub** é outra coisa - é um **serviço web** que hospeda repositórios Git na nuvem e adiciona uma camada de colaboração em volta deles: + +- Um lugar central para o time enviar (`push`) e buscar (`pull`) código - veja [Remote](../3-comandos/remote.md); +- **Pull Requests**: forma de propor e revisar alterações antes de irem para a branch principal; +- **Issues**: para acompanhar bugs, tarefas e ideias; +- Permissões: quem pode ler, escrever ou administrar cada repositório; +- Integrações como GitHub Actions (automação de testes, deploys, etc). + +Ou seja: **Git é a ferramenta, GitHub é onde o time se encontra para usar essa ferramenta em conjunto.** Existem alternativas equivalentes, como GitLab, Bitbucket e Azure DevOps - os conceitos deste capítulo se aplicam a todas elas, apenas com nomes/telas diferentes. + +## Repositório local vs repositório remoto + +``` +Sua máquina GitHub +┌─────────────────────┐ ┌─────────────────────┐ +│ repositório local │ push --> │ repositório remoto │ +│ (git init / commits) │ <-- pull │ (origin) │ +└─────────────────────┘ └─────────────────────┘ +``` + +Todo o trabalho de criar commits, branches, fazer merge, etc. continua sendo feito **localmente** com os comandos que você já aprendeu. O GitHub entra apenas no momento de **sincronizar** (`push`/`pull`/`fetch`) e no fluxo de revisão (**Pull Request**). + +## Permissões básicas + +Na prática, em um repositório de time você normalmente vai se encaixar em um destes cenários: + +- **Você tem acesso de escrita ao repositório**: pode criar branches diretamente nele e abrir Pull Requests a partir delas. +- **Você não tem acesso de escrita** (ex: contribuindo para um projeto de outra pessoa/empresa): você precisa criar um **fork** - uma cópia do repositório na sua conta - e trabalhar nele. Veja o passo a passo em [Fork e Pull Request](fork-e-pull-request.md). + +Ir para: [5.2. Fork e Pull Request](fork-e-pull-request.md) diff --git a/5-github/resolvendo-conflitos.md b/5-github/resolvendo-conflitos.md new file mode 100644 index 0000000..45eccdb --- /dev/null +++ b/5-github/resolvendo-conflitos.md @@ -0,0 +1,79 @@ +# Resolvendo conflitos + +Simplificado: _Quando duas pessoas alteram a mesma linha e o Git não sabe qual manter_

+Conflito de merge é, sem dúvidas, o momento que mais gera pânico em quem está começando. A boa notícia: **é normal**, acontece com todo mundo, e o Git nunca apaga código sozinho - ele só pausa e pede para você decidir. + +## Por que acontece? + +Um conflito surge quando o Git tenta juntar (`merge`, `pull` ou `rebase`) duas branches que alteraram **a mesma região do mesmo arquivo** de formas diferentes. O Git consegue juntar automaticamente alterações em partes diferentes de um arquivo (ou em arquivos diferentes) - o problema é só quando as duas versões "disputam" a mesma linha. + +## Como aparece + +Ao rodar `git merge` (ou `git pull`, que faz merge por trás dos panos): + +``` +$ git merge feature/cadastro-de-clientes +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 cancela nada** - ele marca os trechos conflitantes diretamente no arquivo: + +```html +<<<<<<< HEAD +

Bem-vindo ao sistema

+======= +

Bem-vindo(a) ao nosso sistema!

+>>>>>>> feature/cadastro-de-clientes +``` + +- O que está entre `<<<<<<< HEAD` e `=======` é a versão da branch em que você está (destino do merge); +- O que está entre `=======` e `>>>>>>> nome-da-branch` é a versão que está sendo trazida. + +## Passo a passo para resolver + +1. Abra o(s) arquivo(s) listados como conflito (`git status` mostra todos eles em "Unmerged paths"); +2. Decida o que ficar: a versão de cima, a de baixo, uma combinação das duas, ou algo totalmente novo; +3. **Apague as marcações** `<<<<<<<`, `=======` e `>>>>>>>` - deixe apenas o código final; +4. Marque o arquivo como resolvido: + +```bash +git add index.html +``` + +5. Finalize o merge com um commit (o Git já sugere uma mensagem padrão): + +```bash +git commit +``` + +Se o conflito aconteceu durante um `git pull`, depois de resolver e commitar, finalize enviando suas alterações: + +```bash +git push +``` + +## Em ferramentas visuais + +O VSCode (e a maioria dos editores modernos) detecta automaticamente os arquivos em conflito e mostra botões como **"Accept Current Change"**, **"Accept Incoming Change"**, **"Accept Both Changes"** ou **"Compare Changes"** acima de cada trecho conflitante - você raramente precisa editar as marcações `<<<<<<<` manualmente. + +## E se eu quiser desistir e voltar pro estado anterior? + +```bash +git merge --abort +``` + +Isso cancela o merge em andamento e devolve seus arquivos para como estavam antes de você tentar o merge - sem perder nenhum commit já feito. + +## Conflitos em Pull Requests + +A lógica é exatamente a mesma, só muda onde você resolve: o GitHub avisa "This branch has conflicts that must be resolved" no próprio PR. Você resolve **localmente** (atualizando sua branch com a `main` via `git pull origin main` ou `git merge main`, resolvendo como descrito acima, e fazendo `git push`), e o PR atualiza automaticamente. + +## Como evitar conflitos grandes + +- Mantenha sua branch **atualizada com a main com frequência** (`git pull` / `git merge main` diariamente, não só no final); +- PRs pequenos e de vida curta diminuem a chance (e o tamanho) dos conflitos; +- Combine com o time quem está trabalhando em quais arquivos/áreas do código. + +Ir para: [5.4. Code Review](code-review.md) diff --git a/README.md b/README.md index 87eb8c1..37e96a3 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,24 @@ ### Comandos e Conceitos 1. [Repositório](/3-comandos/repositorio.md) -2. [Config](/3-comandos/config.md) -3. [Commit](/3-comandos/commit.md) -4. [Branch](/3-comandos/branch.md) -5. [Merge](/3-comandos/merge.md) -6. [Status](/3-comandos/status.md) -7. [Diff](/3-comandos/diff.md) -8. [Tag](/3-comandos/tag.md) -9. [Rebase](/3-comandos/rebase.md) -10. [Reset](/3-comandos/reset.md) -11. [Fetch](/3-comandos/fetch.md) -12. [Log](/3-comandos/log.md) -13. [Stash](3-comandos/stash.md) -14. [Cherry-pick](/3-comandos/cherry-pick.md) +2. [Clone](/3-comandos/clone.md) +3. [Config](/3-comandos/config.md) +4. [.gitignore](/3-comandos/gitignore.md) +5. [Commit](/3-comandos/commit.md) +6. [Branch](/3-comandos/branch.md) +7. [Merge](/3-comandos/merge.md) +8. [Status](/3-comandos/status.md) +9. [Diff](/3-comandos/diff.md) +10. [Tag](/3-comandos/tag.md) +11. [Rebase](/3-comandos/rebase.md) +12. [Reset](/3-comandos/reset.md) +13. [Remote](/3-comandos/remote.md) +14. [Push](/3-comandos/push.md) +15. [Pull](/3-comandos/pull.md) +16. [Fetch](/3-comandos/fetch.md) +17. [Log](/3-comandos/log.md) +18. [Stash](3-comandos/stash.md) +19. [Cherry-pick](/3-comandos/cherry-pick.md) ### GitFlow @@ -43,6 +48,13 @@ 4. [Exemplos de GitFlow](/4-gitflow/exemplos.md) 5. [Padrão de Commits](/4-gitflow/padrao-commit.md) +### GitHub + +1. [O que é o GitHub?](/5-github/o-que-e-github.md) +2. [Fork e Pull Request](/5-github/fork-e-pull-request.md) +3. [Resolvendo conflitos](/5-github/resolvendo-conflitos.md) +4. [Code Review](/5-github/code-review.md) + ### Conclusão 1. [Conclusão](/conclusao.md/)