└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Git & GitHub 2 | 3 | A repo for Git & GitHub coaching. 4 | 5 | 6 | ## Requisitos 7 | 8 | - Instalar [git](https://git-scm.com/). É necessário ter algum terminal/prompt de comando com o comando `git` disponível. Verificar com `git --version` ou algum comando semelhante. 9 | - Criar uma conta no [GitHub](https://github.com/) 10 | 11 | 12 | ## Comandos - operações locais básicas 13 | 14 | ### init 15 | 16 | ```sh 17 | git init 18 | ``` 19 | 20 | Cria um repositório git na pasta atual. Ver a pasta oculta `.git`. 21 | 22 | 23 | ### status 24 | 25 | ```sh 26 | git status 27 | ``` 28 | 29 | Mostra o status do repositório local e de seus arquivos. 30 | 31 | 32 | ### diff 33 | 34 | ```sh 35 | git diff 36 | git diff 37 | git diff --staged 38 | ``` 39 | 40 | Mostra as alterações feitas em cada arquivo. 41 | 42 | 43 | ### add 44 | 45 | ```sh 46 | git add [] 47 | git add . # todos arquivos e pastas do cwd, recursivamente 48 | git add -A # todos arquivos e pastas do repositório, independente do cwd ser a raíz 49 | ``` 50 | 51 | Se o arquivo nunca foi commitado, git passa a rastrear (track) o arquivo. 52 | 53 | Se o arquivo já foi commitado, git adiciona ao índice de alterações que farão parte do próximo commit. 54 | 55 | Se não houvesse o `git add`, teríamos que fazer sempre commit de todas as alterações, sem poder de escolha. 56 | 57 | ### commit 58 | 59 | ```sh 60 | git commit -m 'Mensagem do commit' 61 | ``` 62 | 63 | Cria um commit de todas as alterações adicionadas ao índice. 64 | 65 | ### log 66 | 67 | ```sh 68 | git log 69 | git log --oneline 70 | git log --pretty=format:'%h %ad | [%an] %s%d' --graph --date=short 71 | ``` 72 | 73 | Log de commits. 74 | 75 | 76 | ## Arquivos importantes 77 | 78 | `.git` - pasta na raíz do projeto que contém toda base de dados do git do projeto atual. 79 | 80 | `.gitignore` - arquivo na raíz do projeto contendo a lista de arquivos (suporta glob) a serem ignorados pelo git. Binários, dependências, cache de build, credenciais, configurações de IDE. Ex: 81 | 82 | ```text 83 | .project 84 | build/ 85 | node_modules/ 86 | ``` 87 | 88 | `.gitattributes` - arquivo na raíz do projeto, contendo algumas configurações para aquele projeto. 89 | 90 | `.gitconfig` - arquivo na home do usuário, com configurações globais da instalação do git. Ex: 91 | 92 | ```text 93 | [user] 94 | name = Rafael Eyng 95 | email = rafael@exemplo.com 96 | [alias] 97 | l = log --oneline 98 | [color] 99 | diff = auto 100 | status = auto 101 | branch = auto 102 | ui = true 103 | [core] 104 | excludesfile = /Users/rafael/.gitignore_global 105 | ``` 106 | 107 | 108 | ## Comandos - tags, branching 109 | 110 | ### tag 111 | 112 | ```sh 113 | git tag 114 | git tag v1.0.0 115 | git tag v1.0.0 116 | ``` 117 | 118 | Lista ou cria tags. Uma tag é uma referência **fixa** a um commit. Uma tag é vinculada a um commit específico (por default, o atual, indicado por HEAD). 119 | 120 | Ver mais sobre tags em `push`. 121 | 122 | 123 | ### branch 124 | 125 | ```sh 126 | git branch 127 | git branch 128 | git branch -d 129 | git branch -D # force delete 130 | ``` 131 | 132 | Lista, cria, apaga branches. No git, branches não são cópias do projeto, são apenas referências **móveis** para commits. A branch default se chama **master**. 133 | 134 | ### checkout 135 | 136 | ```sh 137 | git checkout 138 | git checkout 139 | git checkout -b # cria e troca para 140 | git checkout -b # cria com o estado da tag especificada 141 | ``` 142 | 143 | Checkout é o processo de pegar uma versão específica do projeto inteiro (ou também de arquivos específicos) do *git directory* e disponibilizar no *working directory*. *Working directory* é a parte do repositório git onde você trabalha (suas pastas e arquivos), diferente do *git directory* (a pasta .git), onde git armazena seus dados. 144 | 145 | 146 | ### merge 147 | 148 | ```sh 149 | git merge 150 | ``` 151 | 152 | Faz merge da branch especificada com a branch atual. 153 | 154 | O merge é a maneira mais comum de integrar branches. Na maior parte dos casos, git consegue resolver o merge automaticamente. Se houverem alterações conflitantes nas duas branches, é necessário resolver o merge e fazer um commit da resolução. Em geral só existem conflitos se a mesma linha de um arquivo foi alterada de forma diferente em cada branch. 155 | 156 | Pensando no grafo de commits, o merge cria um novo nodo (um commit) com referência para 2 ou mais commits pais. 157 | 158 | 159 | ### rebase 160 | 161 | ```sh 162 | git rebase 163 | ``` 164 | 165 | Faz rebase da branch especificada **no topo** da branch atual. 166 | 167 | É uma alternativa ao merge para integrar branches. Diferentemente do merge, não cria um novo commit que aponta para os commits pais, mas sim "corta fora" a branch alvo e reaplica ela, commit a commit, na ponta da branch atual. 168 | 169 | 170 | ## GitHub repositories 171 | 172 | ### organization, repository, team 173 | 174 | Demonstração no navegador. 175 | 176 | 177 | ## Comandos - trabalhando com remotes 178 | 179 | **remote** - um repositório remoto do projeto, com o qual nosso repositório local se comunica. Normalmente em um serviço como GitHub, mas não necessariamente. O remote default se chama **origin**. 180 | 181 | 182 | ### remote 183 | 184 | ```sh 185 | git remote 186 | git remote -v 187 | git remote add 188 | ``` 189 | 190 | Lista os remotes, adiciona novos remotes, remove remotes etc. 191 | 192 | 193 | ### clone 194 | 195 | ```sh 196 | git clone 197 | git clone 198 | ``` 199 | 200 | Cria um repositório local clonado a partir de um repositório remoto. 201 | 202 | Em um projeto em equipe, a pessoa que cria o projeto dá `git init` e manda para um remote. Todos os demais dão `git clone` a partir desse remote. 203 | 204 | Quando clonamos um repositório de um remote, este remote automaticamente é adicionado com o nome de origin. 205 | 206 | 207 | ### pull 208 | 209 | ```sh 210 | git pull 211 | git pull 212 | ``` 213 | 214 | Atualiza a branch local com o conteúdo da branch remota. Se a ponta das duas branches for diferente, requer merge. 215 | 216 | 217 | ### push 218 | 219 | ```sh 220 | git push 221 | git push 222 | git push --tags # tags precisam de um push específico 223 | ``` 224 | 225 | Atualiza a branch remota com o conteúdo da branch local. Se a ponta das duas branches for diferente, requer pull + merge antes do push. Ou seja, o conflito é resolvido localmente, não remotamente. 226 | 227 | 228 | ## GitHub issues & pull requests 229 | 230 | ### issues e pull requests 231 | 232 | Demonstração no navegador. 233 | 234 | 235 | ## Tópicos especiais 236 | 237 | ### branch para "backup" 238 | 239 | Quando você vai fazer alguma coisa que não tem muita certeza, pode criar uma branch de "backup" para voltar com segurança a um ponto anterior. Simplesmente faça: 240 | 241 | ```sh 242 | git branch # qualquer nome não usado ainda 243 | ``` 244 | 245 | Tudo o que você fez é criar uma referência (o nome da branch) a um ponto específico do projeto ao qual você pode querer voltar, usando um `git checkout `. 246 | 247 | 248 | ### desfazendo alterações locais 249 | 250 | Para desfazer as alterações de algum arquivo: 251 | 252 | ```sh 253 | git checkout -- 254 | ``` 255 | 256 | Para desfazer o `git add` de algum arquivo: 257 | 258 | ```sh 259 | git reset 260 | ``` 261 | 262 | Cuidado com esses comandos. Eles não são intuitivos, e são comandos que podem fazer você apagar código que não queria. Recomendo usar as ferramentas (SourceTree etc) para fazer essas ações. 263 | 264 | `checkout` e `reset` fazem diversas coisas diferentes de acordo com as flags que recebem. É interessante ler a documentação desses comandos. 265 | 266 | 267 | ### reescrever história 268 | 269 | Certos comandos de git reescrevem a história do projeto, ou seja, permitem apagar ou alterar objetos existentes do grafo de commits. Em certos casos isso não gera problemas, mas em geral deve ser evitado. 270 | 271 | A regra é: **não reescreva algo que você já enviou para um remote**. 272 | 273 | Ou seja, se você criou um commit no seu repositório local, você pode escolher apagá-lo sem problemas. Mas se você já enviou esse commit para o remote e apagá-lo no repositório local, pode gerar sérios conflitos com a versão do remote ou com outro desenvolvedor que já havia baixado aquele commit. 274 | 275 | 276 | ### revertendo um commit 277 | 278 | Para commits que já sofreram push, é recomendável usar a técnica de fazer um novo commit desfazendo as alterações que foram introduzidas por esse commit que você deseja apagar. Ferramentas como GitHub Desktop e SourceTree fazem isso automaticamente, com a opção **Revert commit**. 279 | 280 | Para commits locais que não sofreram push, pode-se usar: 281 | 282 | ```sh 283 | git reset --hard HEAD~1 # CUIDADO! Você vai perder o último commit 284 | ``` 285 | 286 | onde `1` é o número de commits que se deseja voltar, contando a partir do HEAD. Estamos literalmente voltando a ponta do grafo em 1 commit e perdendo referência para o commit "apagado". 287 | 288 | 289 | ### amend 290 | 291 | ```sh 292 | git commit --amend 293 | ``` 294 | 295 | Este comando refaz o último commit, adicionando ao commit tudo que estiver na *staging area* (tudo que sofreu `git add`). É uma forma de reescrever a história do último commit. **Não usar se o commit já sofreu push**. 296 | 297 | Serve para alguns cenários comuns: 298 | 299 | 1. reescrever a mensagem do último commit 300 | 1. adicionar/remover ao último commit alguma coisa que esquecemos, e que não queremos fazer em um novo commit 301 | 302 | 303 | ### reset hard / soft 304 | 305 | Duas situações comuns podem ser resolvidas com `reset --hard` e `reset --soft`. 306 | 307 | 1. Quando você está com muitas alterações e quer desfazer todas de uma vez: 308 | 309 | ```sh 310 | git reset --hard # se houver arquivos "untracked", é necessário fazer um `git add -A` antes para o git rastreá-los 311 | ``` 312 | 313 | 1. Quando você quer desfazer o último commit (**não usar se já fez push do commit**) mas não perder as alterações que ele introduziu: 314 | 315 | ```sh 316 | git reset --soft HEAD~1 317 | ``` 318 | 319 | Isso irá desfazer a ação do commit, mas não as alterações que o commit introduziu. As alterações estarão na **staging area** da mesma forma que elas estavam antes de executar o commit. 320 | 321 | 322 | ### merge vs rebase 323 | 324 | Embora o merge seja geralmente mais cômodo de fazer, rebase é geralmente considerado uma técnica superior. O use de rebase faz a história do projeto ficar mais linear do que expandida, e evita commits de resolução de merge. 325 | 326 | Rebase é um comando complexo que suporta diversas nuances. Existem projetos que adotam a técnica de "um commit por pull request", para manter um histórico mais conciso e legível. O desenvolvedor pode trabalhar em sua branch local fazendo diversos commits, e antes de fazer push para o remote, usar rebase para fazer *squash* dos commits em um só. Veja a documentação para mais detalhes. 327 | 328 | 329 | ### stash 330 | 331 | Às vezes estamos trabalhando em alguma alteração e precisamos parar para resolver alguma outra coisa no projeto. Geralmente isso envolveria uma troca de branches, ou resetar tudo o que fizemos até agora e recomeçar depois. Nesses casos, geralmente essas condições são verdadeiras: 332 | 333 | - não queremos que nossas alterações (ainda não fizemos commit) em uma branch sejam levadas para a outra 334 | - não queremos fazer commit pois a tarefa está incompleta 335 | - não queremos desfazer e perder as alterações 336 | 337 | `git stash` é um comando que "coloca de lado" todas nossas alterações atuais, em uma pilha, e nos deixa com o *working directory* limpo. Quando quisermos aplicar novamente nossas alterações, usamos `git stash pop`. 338 | 339 | Note que o `stash` tem o comportamento default de uma pilha, mas podemos aplicar alterações que não estejam no topo caso já tenhamos empilhado mais coisas. Veja a documentação para mais detalhes. 340 | 341 | 342 | ### pull vs fetch 343 | 344 | Até agora, só nos preocupamos com 2 tipos de branches: *local branches* (branches no seu repositório, nas quais você trabalha) e *remote branches* (branches no remote, nas quais você faz pull ou push). 345 | 346 | Existe um terceiro tipo de branch, as *remote-tracking branches*. São branches **locais**, que fazem referência ao estado de branches **remotas**. Enquanto que uma *local branch* se chama, por exemplo, `master`, uma *remote-tracking branch* se chama `origin/master`, onde `origin` é o nome do remote. Essas branches são atualizadas automaticamente em comandos que acessam a *remote branch* correspondente. 347 | 348 | A diferença dos comandos `pull` e `fetch`: 349 | 350 | - `pull` atualiza a referência de 1 *remote-tracking branch* e de sua *local branch* correspondente. Por exemplo, se você está na `master` e faz `git pull`, suas branches `origin/master` (remote-tracking) e `master` (local) serão atualizadas com o conteúdo da branch no servidor. 351 | 352 | - `fetch` atualiza a referência de **todas** *remote-tracking branches* e de **nenhuma** *local branch*. É uma forma de baixar os dados de todas as branches para sua máquina sem afetar suas *local branches*, apenas suas *remote-tracking branches*. Após um fetch, pode-se fazer um merge ou rebase da *remote-tracking branch* para a *local branch*, como `git merge origin/master`. 353 | 354 | 355 | ### detached HEAD 356 | 357 | Dependendo do que você fizer, pode acabar em *detached HEAD state*. Embora pareça algo muito errado, simplesmente significa que seu HEAD está apontando diretamente para um commit (e não para uma branch, que por sua vez aponta para o commit, que é normalmente a situação do seu HEAD num projeto). 358 | 359 | 360 | ### Git Hooks 361 | 362 | githooks são scripts arbitrários (você define o que quiser) que são executados em função de certos comandos git. Por exemplo, pode-se rodar testes ou build antes de fazer um commit ou um push e interromper o comando caso os testes falhem. 363 | 364 | Para mais detalhes, veja [este post](http://codeheaven.io/simple-git-hooks-with-ghooks/). 365 | 366 | 367 | ### gh-pages 368 | 369 | GitHub fornece um mecanismo simplificado de hospedagem de sites estáticos. Suporta *custom domains* e *gzip*. 370 | 371 | Basta criar uma branch chamada `gh-pages` e dar push para o GitHub. A home do site estático será um arquivo `index.html` na raíz do projeto, e estará disponível em `.github.io/`. 372 | 373 | 374 | ### Submodules & subtrees 375 | 376 | Se você **precisar embutir código reutilizável** (um módulo ou projeto auto-contido) dentro de um projeto que o contenha, e **não puder utilizar algum gerenciador de dependências** para isso por alguma questão específica da tecnologia/framework que estiver utilizando, submodules e subtrees podem ser a solução. Mas somente se não houver alternativa melhor. 377 | 378 | Este tema é complexo e não será tratado aqui. Estas são provavelmente as melhores referências sobre isso: 379 | 380 | [Submodules](https://medium.com/@porteneuve/mastering-git-submodules-34c65e940407#.lqo946vqm) 381 | 382 | [Subtrees](https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec#.kl471llr0) 383 | 384 | 385 | ## Workflows 386 | 387 | ### topic branch 388 | 389 | Existe uma branch estável, a partir da qual são criadas branches para desenvolvimento de features. Quando for desejado integrar a feature, integra-se nessa branch estável através de *pull request* (preferencialmente com *code review*). 390 | 391 | ![topic branch workflow](https://cloud.githubusercontent.com/assets/4842605/12835036/b0842866-cb93-11e5-9197-a2e96a2ee472.png) 392 | 393 | Opcionalmente pode haver uma branch estável de desenvolvimento e uma branch de produção que reflete o estado do sistema no ar, e só recebe da branch de desenvolvimento no deploy de novas versões. 394 | 395 | 396 | ### git flow 397 | 398 | O git flow prevê um rígido esquema de branches, com 5 tipos de branches diferentes: features, development, releases, master e hotfixes. 399 | 400 | ![git flow workflow](https://cloud.githubusercontent.com/assets/4842605/12835086/29f607be-cb94-11e5-9ead-c60ca7c6468e.png) 401 | 402 | 403 | Referências: 404 | 405 | [A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) 406 | 407 | [git-flow cheatsheet](http://danielkummer.github.io/git-flow-cheatsheet/) 408 | 409 | ### referência de workflows 410 | 411 | Veja o guia da [Atlassian](https://www.atlassian.com/git/tutorials/comparing-workflows) 412 | 413 | 414 | ## Ferramentas recomendadas 415 | 416 | - [SourceTree](https://www.sourcetreeapp.com/) 417 | - [GitHub Desktop](https://desktop.github.com/) 418 | - [git for windows](https://git-for-windows.github.io/) 419 | - [SmartGit](http://www.syntevo.com/smartgit/) 420 | - [Waffle](https://waffle.io/) 421 | - [git flow](https://github.com/nvie/gitflow) 422 | - [GitUp](http://gitup.co/) 423 | - [ghooks](https://github.com/gtramontina/ghooks) 424 | 425 | 426 | ## Materiais recomendados 427 | 428 | [Pro Git](https://progit2.s3.amazonaws.com/en/2016-01-30-9e7cf/progit-en.1005.pdf) - free PDF e-book 429 | --------------------------------------------------------------------------------