leandronsp Profile picture
Dec 4 36 tweets 18 min read
Entender os fundamentos de Git é necessário para quem não quer se deixar dominar pela ferramenta.

Nesta 🧵 vou tentar explicar as estruturas fundamentais do Git e como estas se relacionam com os comandos que usamos no dia-dia.
Os principais componentes do Git são:

.git/objects
.git/refs
HEAD
Começamos pelo Object database, que é basicamente onde o Git armazena todos os seus objetos.
Mas que tipo de database é este? SQL? NoSQL?

Vamos primeiro persistir um objeto utilizando o comando `git hash-object`, que:

* permite input do STDIN ou arquivo normal
* retorna uma hash SHA-1
* persiste com a opção `-w`
Podemos reparar que Git persistiu nosso objeto em .git/objects como era esperado, utilizando a hash que foi devolvida como "chave" de acesso
Se temos a hash, conseguimos resgatar o valor original do objeto?

Sim, com o comando `git cat-file`.

Temos no Git, então, um database baseado em chave-valor, com suas chaves em formato SHA-1.
O comando `cat-file` permite passar a opção `-t` que devolve o tipo do objeto, que neste caso, é um blob.
Uma vez com os blobs persistidos, como podemos agrupá-los, adicionar metadados e criar snapshots?

Precisamos promover estes blobs para um uma área de "Stage", com o comando `git update-index`
Podemos adicionar quantos blobs quisermos ao índice utilizando o `update-index`.

Mas como agrupá-los para que sejam promovidos? O Git permite criar uma "árvore" com esses blobs, através do comando `write-tree`.

Note que novos objetos foram criados, que tipos são esses objetos?
Estes objetos são do tipo "tree", que servem para agrupar diferentes blobs e inclusive outras trees quando utilizada a opção `prefix`
E se quisermos adicionar metadados a partir das trees, como por exemplo o autor do trabalho, a data e uma mensagem descritiva?

Sim, estamos falando do comando `git commit-tree`, que promove uma tree de modo a que esta possa ter metadados.
Commits também são objetos, e portanto, possuem uma chave SHA-1 para representar cada commit.
É possível também criar commits com referência a outros commits (parents).

Repare que o objeto commit tem referência para a tree e para o parent (outro commit criado a partir dele).
Como percorrer toda a "rede" de commits a partir do último commit, indo pelos parents, trees até chegar nos blobs?

O comando `git log <sha1>` faz exatamente isso, percorrendo todo o grafo e trazendo tudo de acordo com a linha do tempo.
Git é baseado em grafos.

Manipular objetos no Git é como manipular ponteiros em grafos.

Blobs representam arquivos. Trees representam conjuntos de blobs e outras trees. Commits representam metadados com referência a trees e outros commits.
Executar toda hora `git log <sha1>` não é eficiente pois temos de decorar as hashes.

Mas Git traz uma facilidade para isto, que são referências para commits, que ficam em .git/refs.

Através do comando `update-ref`, criamos referências que são basicamente commits "com nomes".
Soa familiar? Estamos falando de branches.
Mas o quê acontece se não passar argumento (sha-1) para o comando `git log`?

Como o Git sabe que a minha branch atual é a "main"?
Acertou, é aqui que entra o tal do HEAD.

Com o comando `git symbolic-ref` podemos mudar o ponteiro do HEAD, que é uma referência simbólica para a branch atual de trabalho.

O HEAD pode ser qualquer branch ou até mesmo um SHA-1 (no modo detached)
Trocar o HEAD é uma simples chamada ao `symbolic-ref`.

Neste exemplo, fico intercalando entre a branch "main" e branch "fix".
Agora que sabemos que tudo em Git é manipulação de ponteiros, vamos associar este conhecimento com os comandos do dia-dia.

Começando pelo `git add`, que basicamente é a junção do `hash-object` com `update-index`.
O `git commit` é basicamente o `write-tree` (uma vez que há objetos no index) seguido do `commit-tree`, que adiciona informações como autor, date e message.
Já o `git checkout` é literalmente o `symbolic-ref`, que muda o ponteiro (branch) do HEAD.

Com algumas opções adicionais que trazem mais versatilidade.
O comando `git reset` permite mudar o ponteiro da branch, tal como o `update-ref`.

Sem a opção `--hard`, todos os arquivos que divergem ficam em stage a espera de novo commit.
E o merge?

Bem, é super tranquilo entender. Supondo que temos uma branch main e outra "fix", onde fix está 1 commit à frente.

O merge basicamente faz move a branch main para o mesmo commit da branch fix (fast-forward).
E quando a main tem algum commit à frente da branch fix? Neste caso, não é possível fazer fast-forward.
Mas o Git é bem inteligente e trata desta forma:

* Tira snapshot do parent em comum com ambas as branches
* Tira snapshot do commit da branch de destino
* Tira snapshot do commit da branch de origem

E, por fim, cria um commit adicional de "merge". Sim, é o "three-way" merge.
Onde entra o cherry-pick? Com cherry-pick de um commit da branch main, o Git:

* move o ponteiro da branch fix
* aplica o commit da branch main como último commit na branch fix
E quando queremos aplicar as mudanças por cima de outra branch?

Entra o rebase.

Neste cenário, com rebase a partir da branch fix, basicamente:

* muda o ponteiro p/ o HEAD da main
* faz cherry-pick dos commits q sobraram
* por último muda ponteiro para o último do cherry-pick
E as branches remote?

Também são referências.

O comando `git fetch` faz download da branch do server e sincroniza com uma branch "upstream" relacionada à tracking branch (local).
Por serem branches, é possível fazer merge a partir das branches upstream com as locais.

Geralmente, por estarem sempre "atrás", merges com branches upstream são feitos no modo fast-forward.

O comando `git pull` facilita a vida, fazendo fetch + merge para nós.
"Okay, fiz meu trabalho e agora quero mandar de volta para o server. Como atualizo a branch upstream?"

Não precisa, o comando `git push`, além de atualizar o server, também sincroniza a branch tracking local com a upstream.
Assim como branches, tags também são referências com "nome".

Mas são imutáveis, ou seja, para mudar a referência de uma tag é preciso apagá-la e criar outra com mesmo nome.
Como o @coproduto destacou, nesta thread foram apresentados os comandos "plumbing", que foram os building blocks do Git, e como se relacionam com os comandos "porcelain", usados no dia-dia.

@coproduto E pra quem tiver interesse, o próprio guia oficial do Git é bem completo, se ler os primeiros capítulos já cobre muita coisa boa para dominar mais o Git.

Com destaque ao capítulo 10 que fala dos "internals" que eu trouxe à thread.

git-scm.com/book/en/v2/Get…

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with leandronsp

leandronsp Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @leandronsp

Oct 17
Race Condition 🏎️💥🚗

Pra explicar race condition, eu costumo buscar um pouco no modelo computacional as razões para isto existir.

Entendendo race condition em 10 passos, a thread 🧵
Um programa por vez

Num cenário primitivo sem concorrência, os programas ficam em fila à espera para que possam utilizar os recursos físicos.

Um programa de cada vez.

Aqui, não há qualquer tipo de race condition, era assim que se desenvolvia programas nos anos 40. Image
Ociosidade da CPU

O problema deste modelo primitivo é que, quando o programa fica à espera de I/O (impressora, tela, etc), a CPU fica ociosa, causando assim um desperdício de recursos físicos. Image
Read 12 tweets
Sep 5
SQL 101

Como gerar volume de dados para testes no PostgreSQL com CTE's, com explicação detalhada de cada statement, mais precisamente SELECT, FROM e WITH.

Segue a 🧵👇
SELECT

O statement SELECT permite projetar informações a partir de estruturas de tabelas. Com isso podemos projetar qualquer tipo de informação em um SELECT.
Inclusive dá pra projetar colunas com aliases/labels, desta forma ao invés de ficar "?column?", pode-se definir uma label mais apropriada com "AS".
Read 22 tweets
Aug 26
Aproveitar o assunto, quero deixar meus 2 centavos empíricos sobre algo que raramente escrevo aqui:

*Testes em Software*

Minha reflexão é uma mistura de sentido empírico com base na minha experiência e algum estudo do que no sentido concreto ou literal.

Testes, a thread 🧵
Primeiramente, como devemos testar um componente de software?

Eu começo dizendo que o teste de um componente é uma forma de refutar seus comportamentos, independente de quais sejam.

+
Teste refutado (fail)

Neste caso, há a presença de um bug. É necessário então implementar código para que o teste deixe de ser refutado e que aquele bug em específico possa ser solucionado.

+
Read 22 tweets
Aug 26
não to lembrado ou não conheço um guia oficial de linguagem de programação que tenha feito uma explicação tão sólida e clara sobre Stack e Heap como o guia de Rust

doc.rust-lang.org/book/ch04-01-w…
btw dá pra aprender muitos conceitos de computação enquanto aprende-se Rust pelo guia oficial.

não que seja algo inovador, mas com tal clareza e didática, desconheço outro.
linguagens que aprendi por guia oficial:

ruby
python
elixir
clojure
haskell
golang
kotlin
rust
Read 4 tweets
Aug 4
ultimamente to numa de impulsionar conteúdo bom, então vou deixar na thread links de blogs (dos que acompanho no dev.to) de pessoas que eu sigo por lá.

quem tiver links pra compartilhar, manda aqui também 💪

🧵
simplesmente a melhor.

sou fã do conteúdo que a @anakbns produz e da forma que ela explica as coisas. pra não mencionar que já tive a honra de trabalhar junto :P

dev.to/anakbns
esse aqui, o fera do Linux @____Marcell

dev.to/____marcell
Read 9 tweets
Aug 4
☕️ O quê é OOP?

Sei que vocês estão cansados de ver artigos e threads do tipo, mas vamos nesta 🧵 de 15 passos tentar dissecar algumas características primordiais de OOP através de uma simulação de OOP em, isso mesmo, Bash script.

OOP em Bash, a thread 👇
Se você não tem hábito em Bash script, não há problema.

Os conceitos aqui explicados não exigem conhecimento avançado de Bash, a ideia é apenas tentar entender e simular OOP.
Para implementar OOP, precisamos obedecer algumas regras elementares:

* ter uma forma de representar o estado do objeto
* permitir execução dinâmica de ações no objeto

Claro que há mais coisas envolvidas, mas estas 2 são primordiais para se ter um mínimo de OOP.
Read 17 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(