Repositório criado para treinar comandos do Git.
- Criado por Linus Torvalds em 2005;
- Permite o gerenciamento de versões;
- Registro de modificações;
Para "baixar" um repositório remoto para o local:
$git clone URL
Para iniciar um Repositório Local sem o Clone:
$git init
$git add ...
Adicionar Arquivos:
$git add --all (Adiciona Todos)
$git add *.c (Adiciona Todos os Arquivos .c)
$git add Arquivo.arq (Adiciona um único Arquivo)
Salvar mudanças realizadas (Commit):
$git commit -m "Mensagem...." (Salva os arquivos Adicionados)
$git commit -a -m "Mensagem...." (Adiciona todos os arquivos e Salva)
Subir Mudanças para o Repositório Remoto:
$git push -m origin NomedaBranch (Origin significa o Repo Remoto)
$git push --set-upstream origin NomedaBranch (--set-upstream utilizado para rastrear o branch remoto, geralmente é usado pela 1ªvez, depois só usar Push)
Baixar Mudanças do Repositório Remoto:
$git pull
Buscar tags e branchs remotas, assim como sincronizar mudanças no repositório remoto:
$git fetch
Lista de todas as Branchs do Repositório:
$git branch (A Branch que você está ficara destacada)
Criar uma nova Branch
$git branch NomeDaBranch
Mudar de Branch
$git checkout NomeDaBranch
Uma forma Automatica de criar e já mudar de Branch
$git checkout -b NomeDaNovaBranch (Já cria e da Checkout na nova Branch)
Merge entre duas Branchs
- Suponha que você tem duas Branchs: Main e Feature, e você quer mesclar a feature na Main.
$git checkout Main
$git merge Feature
- Suponha que você tem duas Branchs: Main e Feature, e você quer mesclar a Main na Feature.
Esta parte é relevante, pois suponha que você esteja trabalhando na Feature, e enquanto isso uma Hotfix foi realizada na Main. Assim, você pode mesclar a Mestre na Feature, para ter uma versão mais atualizada, e quando o Merge da FFeature for realizada na Main, o código vai estar atualizado.
$git checkout Feature
$git merge Main
🚧 Importante! Evitar usar Rebases em Commits que já tenha sido enviados para o repositório remoto.
O Git Rebase tem como objetivo de reaplicar os commits realizados em outra base. Por exemplo:
- Suponha que você está na Branch Topic. E Ocorreram dois commits
A---B---C topic
/
D---E---F---G master
- Caso deseja aplicar os commits F e G ao topic, é possível realizar um Rebase da Branch.
git rebase master
git rebase master topic
- O resultado é F e G.
A'--B'--C' topic
/
D---E---F---G master
O Rebase também pode funcionar para editar e manipular commits já ralizados:
git rebase -i HEAD~3
No Windows, quando o comando for executado, ira abrir um novo arquivo. Para salvar, deve-se apertar ESC e depois escrever :wq.
O número "3" em HEAD~3, significa que será buscado 3 Commits desde o último.
Para editar, existem alguns comandos:
- Reword: Edita a mensagem do Commit;
- Squash: Combina Commits
O Comando Reflog apresenta de forma detalhada todas as últimas ações executadas. Cada ação tem um Hash que pode ser usado para outras ações de correção de erro.
632744c HEAD@{2}: commit: Oi Mundo em Turco
54d918b (HEAD -> main) HEAD@{3}: commit: Alemao na Main
7bbf312 (origin/main, origin/HEAD) HEAD@{4}: commit: Readme
ce5577e HEAD@{6}: rebase (pick): Novo Update de GIT
5355cec HEAD@{7}: rebase (reword): Atualização do Arquivo README com dados do Rebase.
218429b HEAD@{8}: rebase: fast-forward
468e783 (origin/hotfix-language, hotfix-language) HEAD@{9}: rebase (start): checkout HEAD~3
c13cb85 HEAD@{10}: rebase (abort): updating HEAD
c13cb85 HEAD@{11}: rebase (abort): updating HEAD
c13cb85 HEAD@{12}: rebase (abort): updating HEAD
c13cb85 HEAD@{13}: rebase (abort): updating HEAD
c13cb85 HEAD@{14}: rebase (abort): updating HEAD
c13cb85 HEAD@{15}: rebase (abort): updating HEAD
c13cb85 HEAD@{16}: rebase (abort): updating HEAD
Suponha que um commit 632744c tenha sido excluído, e você percebe que foi um erro e decide restaurar. Para isso, pode-se utilizar um truque simples:
git branch correcao-turco 632744c
Você cria uma Nova Branch a partir do Hash excluído. Tudo será recuperado.
Como o Reflog também é possível recuperar branchs excluídas seguidno mesmo processo.
e34dfe9 (HEAD -> main, origin/main, origin/correcao-turco, origin/HEAD, correcao-turco) HEAD@{0}: checkout: moving from nova-feature to main
c0e1e67 (origin/nova-feature) HEAD@{1}: checkout: moving from main to nova-feature
e34dfe9 (HEAD -> main, origin/main, origin/correcao-turco, origin/HEAD, correcao-turco) HEAD@{4}: checkout: moving from main to nova-feature
e34dfe9 (HEAD -> main, origin/main, origin/correcao-turco, origin/HEAD, correcao-turco) HEAD@{5}: merge correcao-turco: Fast-forward
54d918b HEAD@{6}: checkout: moving from correcao-turco to main
e34dfe9 (HEAD -> main, origin/main, origin/correcao-turco, origin/HEAD, correcao-turco) HEAD@{7}: commit: Commit recuperado e Readme Reflog
632744c HEAD@{8}: checkout: moving from main to correcao-turco
- e34dfe9: Foi movido da Feature nova-feature para main (No caso, a Branch foi excluída, tanto no local quanto no remoto)
Para recuperar, foi utilizado o comando git branch, e indicando o mesmo nome da branch, e o HASH de quando foi realizado o checkout para a Branch deletada.
git branch nova-feature c0e1e67
Trabalhar com Submodule pode ajudar a importar bibliotecas e arquivos de outros repositórios. A função é muito simples:
git submodule add URL
Ao executar o comando, o repositório e seus arquivos são clonados diretamente para o seu repositório.
❗️ Importante! Em caso de clonar um repositório que já tenha outros submódulos, as pastas de cada um deles vem vazia. Para isso, alguns comandos de update podem ser utilizados:
git submodule update --init --recursive
ou
git clone --recurse-submodules URL
Para atualização convencional, basta utilizar o seguinte comando:
git submodule update --remote
É provável que ao utilizar sub-módulos tenha interesse em atualizar os fontes do sub-módulo e ao mesmo tempo puxar atualizações. Vejamos a seguinte situação:
- Atualização do Sub-Módulo(SM) e Depois executar o comando de update:
Aqui ocorre o seguinte, ao aplicar o comando submodule update, todas as modificações realizadas pelo desenvolvedor no sub-módulo serão perdidas, pois substituirão as modificações.
Uma forma de contornar essa situação é aplicar o seguinte comando:
git submodule update --remote --merge
Ou seja, as atualizações serão mescladas no repositório do projeto.
❗️ Atenção! Para que as modificações sejam mescladas, o Sub-Repositório precisa estar em uma branch diferente da detached HEAD. Para isso, basta entrar na pasta do sub-repositório e usar o comando
git checkout branchname
, comitar as mudanças e depois usar o comandogit submodule update --remote --merge
.
Sub-tree é uma estratégia alternativa ao submodule. Para esse caso existem algumas vantagens:
- Gerenciar um fluxo simples;
- Projeto e arquivos disponíveis logo depois de aplicar git clone, sem a necessidade de usar o comando de atualização;
- Usuários não precisam aprender nada novo de git para usar.
Para usar, basta aplicar o seguinte comando:
git subtree add --prefix {local directory being pulled into} {remote repo URL} {remote branch} --squash
--squash
é um comando para suprimir todo o histórico antes do subtree adicionado.
Para atualizar o fonte da Subtree:
git subtree pull --prefix {local directory being pulled into} {remote repo URL} {remote branch} --squash
❗️ Cuidado com os conflitos ao utilizar o pull.
Para enviar atulizações:
git subtree push --prefix {local directory being pulled into} {remote repo URL} {remote branch}
Apesar de possuir comandos simples, como pull e push, existem algumas desvantagens de utilizar subtrees:
- Utilizar subtrees com multiplos sub-repos pode ser um problema.
Para ver um exemplo de Tree com subtree, basta ver o Anexo.md
De acordo com autor (@ingydotnet) o Sub-Repo é uma melhoria das outras duas alternativas, sub-tree e sub-module. São listados alguns benefícios:
- Execução por linha de comando simples e intuitivas;
- Usuarios clonam o repositório e sub-repositórios de forma direta;
- Existe o arquivo .gitrepo para rastreio e identificação;
- Branchs diferentes podem ter diferentes subrepos em diferentes estados;
- ...
Para clonar um subrepo, basta utilizar o comando:
git subrepo clone <repository> [<subdir>] [-b <branch>]
Obs. Existem outros comandos que podem ser utilizados, como: git subrepo clone <repository> [<subdir>] [-b <branch>] [-f] [-m <msg>] [-e] [--method <merge|rebase>]
.
Também é possível tornar um subdiretório em um subrepo:
git subrepo init <subdir> [-r <remote>] [-b <branch>] [--method <merge|rebase>]
Para puxar as novas atualizações do repositório remoto:
git subrepo pull <subdir>|--all [-M|-R|-f] [-m <msg>] [-e] [-b <branch>] [-r <remote>] [-u]
Enviar atualizações:
git subrepo push <subdir>|--all [<branch>] [-r <remote>] [-b <branch>] [-M|-R] [-u] [-f] [-s] [-N]
Adicionar a branch do subrepo como um único commit na história principal:
git subrepo commit <subdir> [<subrepo-ref>] [-m <msg>] [-e] [-f] [-F]
❗️ A função commit não é tão trivial quanto ao modo convencional. Neste caso, a branch do subrepo é adicionado ao fluxo de história principal. Para comitar mudanças, basta utilizar o commit normalmente.
- Push (Enviando atualizações para o repositório remoto originário do subrepo)
git subrepo clone.....)
git subrepo pull --force repotest
git commit -a -m "msg"
git subrepo push repotest
- Pull e Merge (Mesclando atualizações próprias do projeto, com desenvolvimento remoto)
Suponha que ao clonar um subrepo par ao seu projeto, você precisa edita-lo para customizar algumas opções. Portanto, é interessante e necessário que atualizações internas e externas(repositório original) sejam mescladas, para não perder ou prejudicar o andamento do projeto. Nesta situação, ao aplicar a função pull
, deve-se utilizar a opção -M --merge
.
git subrepo pull -M --merge repotest
Quando ocorre o Merge, o fluxo é semelhante ao mostrado abaixo:
A---B---C subrepo
/ \ (git subrepo pull <subdir> -M --merge)
D---E---F---G---H Repositório Remoto
O Repositório Remoto (origem do subrepo) não sofre alteração com o Pull, ou seja
Abaixo um exemplo real retirado de um repositório de teste:
* commit 45b74374d280b7477d92abed199aa8837c4dbd20 (refs/subrepo/repotest/commit, refs/subrepo/repotest/branch, subrepo/repotest)
|\ Merge: cacbb10 b50d992
| |
| |
| |
| | Merge commit 'refs/subrepo/repotest/fetch' into subrepo/repotest
| |
| * commit b50d992cd50a222654d112a74a1dfac2eaf47212 (refs/subrepo/repotest/fetch)
| |
| |
| |
| | fun11
| |
* | commit cacbb106533ebd9aaf555ff8b38bb40ed479ca40
|/
|
|
|
|
* commit b4df05c88ac3ed1cfce563357ddf7aee3129613a
O Rebase segue a mesma lógica do convencional. Ao realizar o comando, o fluxo de commits é reposicionado conforme o diagrama abaixo:
A'--B'--C' Sub Repo
/ (git subrepo pull <subdir> --method --rebase)
D---E---F---G Repositório Remoto
Sempre importante relembrar que é preciso ter cuidado ao aplicar o Rebase com atualizações já enviadas para o upstream.
- Branch Remoto (Puxar e enviar desenvolvimento de Branchs diferentes)
Ao trabalhar com subrepo, pode ser necessário a puxar do repositório remoto, outras branchs da principal. Para isso, basta usar o comando -b <branch>
.
git subrepo pull --force repotest -b NomeDaBranch
git commit -a -m "Atualizações"
git subrepo push repotest
O comando push pega a branch do último pull e envia, portanto não é necessário especificar qual branch será enviado o desenvolvimento. Caso seja necessário mudar a branch, basta especificar o nome da branch no push -b <branch>
.
- Pull e Rebase
Quando é utilizado o comando Rebase ao realizar um Pull, o fluxo/histórico de commits fica reorganizado em uma linha histórica. Observe o Exemplo abaixo, onde a seguinte situação foi aplicada:
c1sub----------c3sub-------------c5sub--pull -M -rebase (subrepo)
/ /
---Inicio-------c2repo-----------c4repo--------/ (repositório remoto)
Foram realizados commits alternados entre o projeto (subrepo) e o repositório remoto que deu origem ao subrepo. Ao realizar o pull -M --rebase
no subrepo, identifica-se que o fluxo de commits resulta em uma linha única de histórico, com os commits do repositório remoto no topo, e os demais em sequência. Compare o fluxo abaixo com o exemplo do pull -M --merge
acima.
* commit 0ca4fa14e3c535a986c5eac0ea865739a19c1cfc (HEAD -> develop, origin/develop)
|
|
|
| git subrepo pull (merge) math_operations_h****
|
|
* commit 10c3a11c44a5fd2485e9567b19f9c495ff341742
|
|
|
| c5sub
|
* commit d9199328b749eae407a84922b615bd7a05302481
|
|
|
| c3sub
|
* commit 64d229cc982a1d7a0f9670bd258115591426a26d
|
|
|
| c1sub
|
****Obs: por algum motivo o subrepo indica a informação git subrepo pull (merge) math_operations_h
com merge. Mas foi applicado rebase.
❗️ Apesar de promissor, o subrepo tem pouco conteúdo e informação na internet.
Foram desenvolvidos 3 projetos como exemplo de aplicação de submodule, subtree e subrepo. Todos eles tulizaram a biblioteca math_operations_h como base para suas aplicações. De forma muito simples, o projeto consiste em uma calculadora, com operações matemáticas básicas provenientes da biblioteca importada. O foco dos repositórios não é o desenvolvimento das operações, mais sim aplicar os comandos e manusear a biblioteca por meio de subrepo, subtree e submodule.
Os três métodos possuem o mesmo objetivo, importar repositórios remotos para dentro de outro repositório ou projeto. Todos possuem bom desempenho, mas alguns se destacam conforme os critérios apresentados abaixo:
Critério | submodule | subtree | subrepo |
---|---|---|---|
Documentação | Alto | Médio | Baixo |
Manuseio Comandos | Alto | Alto | Alto |
Atualização de Repositório Remoto (Push) | Baixo | Alto | Alto |
Dowload de Atualizações (Update) | Alto | Médio | Alto |
Mesclar atualizações (Pull Merge/Rebase) | Baixo | Médio | Alto |
Rastreabilidade | Baixo | Alto | Alto |
Histórico de Commits | Baixo | Alto | Médio |
Multiplos Repositórios importados | Baixo | Médio | Alto |
Organização | Alto | Alto | Alto |
Desempenho = Alto, médio ou baixo;
De forma geral, tanto o subtree quanto o subrepo possuiram melhor desempenho. Ambos possuem comandos mais conhecidos, como Pull, Push e Clone, que são mais familiares, e facilitam o aprendizado. No entanto, alguns deles como merge, commit e branch, podem ser mais complexos. Outro aspecto importante que levam o destaque destes dois métodos é a flexibilidade e atualizações com mesclagens do projeto atual com atualizações do repositório remoto.
Suponha que temos a seguinte situação:
A---B---C topic
/
D---E---F---G master
- Usando o Merge
Podemos aplicar o Merge do topic na master, assim ambos os desenvolvimentos serão mesclados.
>>Mergeq
A---B---C topic
/ \
D---E---F---G---H master
Em H, o projeto irá conter os desenvolvimentos de topic e master mesclados, e em caso de conflitos, os mesmos devem ser resolvidos na hora do merge. No entanto, perceba que os commits A, B e C da Branch topic não consideram os commits F e G da master, o que pode ser um problema, pois as branchs desincronizada podem ocasionar problemas no funcionamento geral.
Neste caso, o ideal é realizar testes com os códigos mesclados antes de enviar para a master. Uma estrutura é utilizar o merge em uma branch dev intermediária a master, que pode ser utilizada para testes, e manipulações antes de ser mesclada na master.
>>Merge
A---B---C topic
/ \
D---E---F---G---H dev
| | | | \*Testes
D---E---F---G-----H master
- Usando Rebase
Com o Rebase, os commits aplicados na Branch topic serão considerados após a o último commit G da master. Este processo "Sincroniza" a branch topic com a master, levando todas as atualizações da branch master para a topic. Com isso, é possível realizar o desenvolvimento na branch topic considerando todas as atualizações feitas na master, e trabalhar nas possíveis implicações que os commits F e G comprometeriam na branch topic.
>>Rebase
A'--B'--C' topic
/
D---E---F---G master
Depois, o comando merge pode ser aplicado para levar o desenvolvimento da branch topic na master.
>>Merge
A'--B'--C' topic
/ \
D---E---F---G-----------H' master
Como G = A' e C'=H', o resultado final fica:
>>Merge
D---E---F---G/A'--B'--H'/c' master
Dessa forma, a linha do tempo no Git fica mais limpa e clara, considerando apenas os commits essenciais.
https://git-scm.com/docs/git-rebase
https://www.youtube.com/watch?v=RGOj5yH7evk&t=2267s&ab_channel=freeCodeCamp.org
https://www.youtube.com/watch?v=Uszj_k0DGsg&ab_channel=freeCodeCamp.org
https://www.youtube.com/watch?v=qsTthZi23VE&t=903s&ab_channel=freeCodeCamp.org
https://www.treinaweb.com.br/blog/git-merge-e-git-rebase-quando-usa-los
https://gist.github.com/SKempin/b7857a6ff6bddb05717cc17a44091202
https://gist.github.com/SKempin/b7857a6ff6bddb05717cc17a44091202