Transcript for:
Apresentação sobre Git por Fábio Akita

Olá pessoal, Fabio Akita e eu finalmente estou de volta. Fiquei uns dois meses meio que de férias, de fim de ano, enquanto eu tava fazendo obra e me mudando pro meu novo apartamento. Ainda não tá 100%, mas vocês já podem ver que o cenário mudou e esse é o piloto de teste da nova configuração de equipamentos. Eu ainda vou refinar mais um pouco e em breve eu faço um vídeo. sobre como eu estou gravando a partir de agora.

Como já estamos em fevereiro, eu nem vou falar de retrospectiva nem nada disso, vamos já pular direto pra um assunto técnico. Na real, eu estou postergando esse tema desde um ano atrás quando eu comecei a série começando aos 40 e E no primeiro vídeo de conhecimentos gerais eu disse que era obrigatório conhecer Git e Linux. Linux eu já fiz um episódio onde falei sobre como instalar e configurar um ambiente de desenvolvimento em Ubuntu, então resta falar sobre Git.

Porém eu já vou avisar que isso não é um tutorial de Git. Uma coisa que eu não estou afim de fazer é tutoriais que você pode facilmente encontrar em qualquer outro canal, ou curso online, ou post de blog. Porque a meia dúzia de comandos básicos de Git é super simples, nenhum inconveniente em poucas horas você já aprendeu e com poucos dias praticando você já devia ser capaz de participar de um projeto. Em vez disso eu quero dar alguns insights que talvez vocês não saibam mesmo se já usam Git faz tempo.

Essa história começa uns 12 anos atrás. Eu lembro bem que era um dia de semana, por volta de 2007, e eu tava voltando de algum cliente ou algo assim no meu carro e naquela época eu ouvia alguns podcasts e audiobooks porque eu gastava muitas horas no carro dirigindo e voltando do trabalho. E um dos programas que eu ouvia naquela época era o Floss Weekly do Leo Laporte, episódio 19, do dia 1º de setembro de 2007. Uma entrevista com Júnior Ramano, entrevistado por ninguém menos que Randall Schwartz, que era bem conhecido na comunidade Pearl.

eu vou deixar o link desse episódio nas descrições abaixo. E eu mesmo preciso ouvir de novo porque eu só ouvi uma vez naquele dia. Pra dar um contexto, nessa época eu tava deixando de ser consultor SAP e programador Java pra experimentar ser freelancer em Ruby on Rails.

Eu contei um pouco disso no episódio sobre SAP e sobre Ruby on Rails, então deem uma olhada. Mas o comum naquela época na maioria das empresas era ou não usar nenhum tipo de controle de versão ou Ou no máximo algum produto comercial bem porcaria como o Microsoft Source Safe ou Rational Clearcase. Mundo open source ainda não tinha tanta força, muitos projetos ainda usavam CVS, alguns poucos estavam indo pra Subversion. A primeira década do século 21 ainda tava muito atrasado em relação a qualidade de vida pra desenvolvedores. Eu era um dos rebeldes chatos que ficavam insistindo em tentar usar pelo menos Subversion no mundo corporativo, porque eu já tinha ficado.

atrizes demais por conta do source safe. Ninguém merece aquele lixo. Eu sofri com source safe desde o ano 2000 e já tava de saco cheio. E mesmo subversion não era nem uma grande maravilha, era mais a filosofia do menos pior mesmo.

E se viesse, quem teve que lidar com essa outra porcaria nos anos 90 lembra o sofrimento. Mundo open source e mundo corporativo estavam bem mal servidos. A entrevista do podcast era com Júnior Ramano, que era e acho que ainda é o mantenedor do Git.

e ele estava justamente explicando que diabos era isso de Git. Em 2007 literalmente ninguém fora dos colaboradores da Kernel do Linux tinham muita ideia sobre isso. Como eu tinha essa péssima experiência com CVS, Subversion, Source Safe e tudo mais, quando eu ouvi a explicação fiquei com vontade de experimentar o quanto antes. Então eu cheguei em casa e fui logo pesquisar. Obviamente tinha pouca coisa online a respeito.

Foi meio um déjà vu, porque foi a mesma sensação quando pesquisei sobre Ruby on Rails uns 2 anos atrás e também não achava ninguém muito interessado. Mas aí esbarrei numa palestra do próprio Linus Torvalds de poucos meses antes. Foi uma tec talk dentro do Google.

Tem um monte de coisas do Google que eu pessoalmente não gosto, mas não se pode negar que eles sempre tentam estar um passo à frente nas tendências. E se tem um vídeo sobre Git que eu diria que deveria ser obrigatório assistir, é essa tec talk de maio de 2007 do Torvalds. Nós literalmente usamos tarballs e patches, que é um sistema de controle de fonte muito superior ao que o CVS é.

Eu acabei usando o CVS por 7 anos em uma empresa comercial e eu odeio com uma paixão. Quando eu digo que eu odeio o CVS com uma paixão, eu também tenho que dizer que se há algum usuário de SVN em subversão, usuários no público, você pode querer sair. Porque o meu hatredo pelo CVS tem significado que eu vejo a subversão como o projeto mais pointless que eu já comecei. Porque o todo... O slogan da subversão por um tempo era CBS done right, ou algo assim.

E se você começar com esse tipo de slogan, não há onde você pode ir. É como se não existisse uma maneira de fazer CBS certo. Você pode desaguar comigo o quanto quiser, mas durante este palco, por definição, quem desaguar é estúpido e feio. Então, mantenha isso em mente. Quando eu terminar de falar, você pode continuar com suas vidas.

Agora, sim, eu tenho opiniões fortes e usuários do CVS, se você realmente gosta de usar o CVS, você deve estar aqui. Você deve estar em alguma instituição mental, em algum lugar. Eu adoro quando o Thorwalds não só pisa no calo, mas puxa o martelo e marreta com força. Em resumo, antes do Git, a manutenção do projeto da kernel do Linux...

era feita literalmente com patches e tarballs, eu vou voltar pra explicar isso já já. Mas aí eles encontraram a ferramenta comercial BitKeeper, que foi um dos primeiros versionadores de código distribuídos e bem feitos. E assim como o GitHub, era uma ferramenta fechada mas que eles deixaram projetos open source usar.

Só que o problema de confiar numa ferramenta comercial é que por um tempo eles podem ser legais e deixar usar de grátis, mas um belo dia eles podem proibir de usar. E foi o que aconteceu. porque alguém tentou fazer engenharia reversa do protocolo deles e se eu não me engano eles não gostaram nada disso e mudaram de ideia.

Daí o Linux ia ficar sem o BitKeeper, obviamente outras porcarias como SourceSafe jamais foram cogitados como alternativa, e nem voltar pra coisas como CVS. A outra opção era voltar ao procedimento anterior de patches e tarballs. Depois de lançar a kernel 2.6, o Torvalds queria resolver esse problema de uma vez por todas.

Ele olhou as opções e pensou assim. Eu realmente olhei para muitas alternativas. A maioria delas eu poderia descartar sem mesmo tentá-las. Se você não é distribuído, você não vale a pena usar.

É tão simples. Se você performa mal, você não vale a pena usar. É tão simples.

E se você não consegue garantir que a coisa que eu coloquei em um SCN saia exatamente igual, você não vale a pena usar. Quase francamente, isso tomou conta de tudo que estava lá fora. Há muitos sistemas de SCM que não garantem que o que você tira de volta seja a mesma coisa que você coloca.

Se você tem corrupção de memória, se você tem corrupção de disco, você pode nunca saber. A única maneira de saber é que você notou que há corrupção nos filhos quando você os avisa. E o sistema de gestão de controle de fonte não te protege de nada. E isso não é nem incomum, é muito, muito comum.

O problema da performance, um dos... E eu não sou contra falar grande se a pessoa entende que a pessoa é uma pessoa que não é uma entrega grande. E Torvalds, como todo mundo sabe, entrega.

E o resultado disso foi o Git que ele desenvolveu por volta de 2015. Antes de continuar, vale eu voltar rapidamente na história. Pensa assim, um programador iniciante hoje, ou um programador nos anos 70, 80, não importa, você tá nos primeiros passos, você quer escrever código, então você abre um editor de textos qualquer e começa a criar arquivos e vai salvando em algum diretório. Muito rapidamente você vai fazendo os mesmos erros que Todo programador sempre caiu não importa em qual época. Você vai escrever em cima do seu código de ontem, salvar e depois descobrir que fez errado e agora perdeu a versão de ontem.

Você vai renomear arquivos, sair apagando e uma hora vai apagar um arquivo que não devia, quem nunca? Depois de apagar coisas por acidente algumas vezes, você vai começar a duplicar os arquivos antes de editar. Daí vai começar a ficar com versões diferentes do mesmo arquivo no mesmo diretório.

Cansei de fazer isso quando era novo e cansei de ver projetos dos outros cheio de arquivos velhos que não deviam estar lá. Daí vem o segundo problema. Você precisa que outro desenvolvedor trabalhe no mesmo projeto. Uma das maneiras de fazer isso é colocar o diretório do projeto em alguma pasta compartilhada na rede local.

Daí acontece de os dois abrirem o mesmo arquivo pra editar. Você edita e salva primeiro. Daí o segundo cara edita a parte dele e salva por cima.

E pronto, você acabou de perder o que estava fazendo. Por isso que muitos produtos comerciais daquela época como o SourceSafe ou o ClearCase, que eu já xinguei várias vezes, Tem como princípio ser uma camada por cima do sistema de arquivos de rede e te dá a opção de bloquear um arquivo ou diretório. Daí antes de abrir um arquivo, primeiro você bloqueia ou faz check-in. Daí se outro programador tentar abrir o mesmo arquivo o sistema vai negar, e ele tem que esperar você terminar, salvar e dar check-out pra desbloquear o arquivo. Isso ajuda um pouquinho, mas não muito.

Eu lembro que no ano 2000 eu trabalhava no Brasil mas na empresa tinha grupos de programadores em Miami, em Buenos Aires e outros lugares da América Latina. Daí um infeliz em Miami bloqueava um arquivo e ia embora sem desbloquear. E eu precisava editar aqui e não conseguia.

Daí tinha que ligar pra alguém que fosse administrador do servidor pra desbloquear forçado. Esse sistema de bloquear e desbloquear era um lixo na prática. Só servia pra casos muito simples. Isso não resolve o problema de alguém ou você mesmo salvar o que não devia. e perder o que tinha antes.

Pra isso precisava ter versionamento. Hoje em dia os próprios sistemas operacionais e mesmo produtos como Dropbox já oferecem um mínimo de versionamento. Mesmo que você apague o conteúdo de um arquivo e grave por cima, você pode optar em pedir pro sistema fazer tipo um backup da versão anterior.

Daí você tem a opção de tentar recuperar algumas versões pra trás. Veja um Time Machine da Apple por exemplo. Hoje em dia a maioria das pessoas tem no mínimo 128GB de HD, mas é muito comum ter meio tera, ou mais que um tera.

O computador que eu uso pra editar meus vídeos tem dois Samsung Evo NVMe 2 de 3 tera cada, sem contar os backups externos. Mas no ano 2000 era luxo ter 10GB de HD, máquina corporativa podia ter menos que isso ainda, e projeto Java naquela época era tão pesado como é Nos anos 90 pra trás, espaço em disco era mais inacessível ainda. O jeito tosco que eu falei acima de duplicar o arquivo antes de editar pro caso de você precisar da versão anterior é super ineficiente, não só porque vai sujando seu diretório com arquivos desnecessários, mas vira um enorme desperdício de espaço caro em disco.

Por isso acho que foi por volta dos anos 70, na época dos UNIX, que surgiram duas ferramentas que existem até hoje nos Linux e devia ser ensinado como parte da matéria de algoritmos e estruturas de dados. A primeira ferramenta se chama Diff, que é usado pra tirar a diferença entre dois arquivos. E aqui é um exemplo de onde estudo de algoritmos faz diferença. Se você como iniciante quiser fazer uma ferramenta que abre dois arquivos e tira a diferença em um terceiro arquivo, como é que você faria? É um problema exponencial que fica lento, muito rápido e se implementar de jeito tosco.

Mas existe um algoritmo bem conhecido. pra encontrar a subsequência comum mais longa entre dois strings. No pior caso a complexidade vai ser de 2 elevado a M, sendo M o tamanho de um dos arquivos. Mas no melhor caso a complexidade cai pra M vezes N, sendo N e M o tamanho dos dois arquivos.

Se fizer da forma ingênua vai ficar exponencialmente pior que isso. Aliás, se vocês estão estudando algoritmos e estruturas de dados na faculdade, eu recomendo estudar esse algoritmo também. O professor de vocês pode ajudar.

Ou também vídeos no YouTube mesmo. com a explicação passo a passo pra entender como você consegue achar essa subsequência. E a partir dessa subsequência, se um conteúdo existe no arquivo original mas não existe na subsequência, podemos marcar com um caracter como"-". Se não existe no arquivo original mas existe na subsequência, podemos marcar com um caracter como"-". Adicione a essa subsequência alguns metadados, como em qual linha do arquivo aquela subsequência se localiza, e chegamos no que chamamos do formato de um.

Então a ferramenta diff que todo Linux tem consegue achar a subsequência comum mais longa entre dois arquivos, adiciona metadados como o número da linha no arquivo e gera esse arquivo de patch. Patch que em inglês é basicamente um remendo. Alguns dizem que essa é a origem do nome Apache, o servidor web que era feito com um monte de patches, ou seja, a patch, por isso Apache. Enfim, Dentro de um arquivo de patch você tem chunks ou ranks de código, que é literalmente NACOs de código.

Vários NACOs de código ou ranks formam um patch, que é um remendo. Daí digamos que você queira mandar as modificações que você fez num arquivo pra um amigo seu que tem o mesmo arquivo. Você envia só o arquivo de patch. E no Linux tem a segunda ferramenta que eu falei que se chama patch e é feito pra aplicar um arquivo de patch.

no arquivo original pra ter a versão nova. Se você já pelo menos andou fuçando um projeto num GitHub da vida já deve ter visto o formato de patches, só que colorizado. Mas é basicamente a mesma coisa. A ferramenta diff nasceu por volta de 1976, então ele é pouca coisa mais velho do que eu. E graças a isso ficou mais econômico guardar só as modificações feitas sobre o arquivo original em vez de duplicar o arquivo toda vez só por causa de uma linha modificada.

Então... economizamos tanto em espaço de disco quanto banda de rede, já que se fosse transferir as modificações pela rede, antes precisava ir o arquivo inteiro modificado, agora pode ir só o patch que vai ser muito menor. E de novo, lembre-se que hoje você tem banda larga com 200 megabits por segundo ou mais, mas antigamente a gente tá falando de linhas discadas ou redes lentas que trafegavam alguns kilobytes por segundo só.

Agora, se você tiver outro programador que tá procurando no mesmo projeto, não basta só dar o patch pra ele. Ele precisa ter alguma versão do projeto baixado pra aplicar esse patch. E como é que ele baixa o projeto? Pensando de novo nos primórdios da internet, uma forma de fazer isso seria baixar de um servidor de arquivos.

Só que eu já expliquei que temos essa limitação de baixa velocidade. Dependendo do tamanho do projeto pode ficar bem lento de baixar. Pensa que antigamente, anos 70 pra trás, disco rígido era uma coisa bem cara. A forma mais comum nos mainframes e minicomputadores era armazenar dados em fitas, em rolos de fitas.

E pra gravar em fita você precisava tentar desperdiçar menos espaço quanto possível. Daí no fim dos anos 70 nasce o formato de gravação de arquivos em fita ou tape archive, que você conhece hoje como TAR. A estrutura de dados de um TAR é gravar uma série de objetos um atrás do outro.

TAR é traduzido literalmente como alcatrão, poluente de petróleo. Mas pense mais como um um piche. Então se você tem uma bola de piche onde objetos vão grudando, você tem um tar ball. Daí que vem esse termo que todo mundo de Unix e Linux sempre usa mas você nunca soube o que era. Na prática pense que em vez de ter 100 arquivos separados, você combine os 100 um atrás do outro num único arquivão.

A grosso modo isso é um tar. E pra ser eficiente, o comando tar dos Unix e Linux tem a capacidade de adicionar compressão sem perda a partir dos anos 90. E aliás, compressão existem dois tipos, lossy e lossless, ou seja, compressão que perde dados e compressão que não perde dados. Exemplos de compressão lossy que perde dados é JPEG pra imagens ou MP3 pra música. Exemplos de compressão que não perde dados é ZIP, 7-ZIP.

A compressão mais simples que você mesmo pode aprender sozinho e deveria ser ensinado na faculdade na matéria de algoritmos e estruturas de dados é o algoritmo de Huffman pra compressão de texto. O formato gzip que você vê até hoje em Linux usa o algoritmo deflate, que é uma combinação de uma variação do Lempel-Ziv e do Huffman. Aliás, algoritmos de compressão é outra área que os russos dominam.

Se você já ousou ou ouviu falar de RAR, o nome vem de Roshal Archive, que é o nome do inventor russo Eugenie Roshal. O zip e o 7zip vem de outro russo, Igor Pavlov. No fim dos anos 80 um dos compressores mais famosos na época do MS-DOS era o PKZip que eu usei bastante, mas nesse caso era do americano Phil Katz.

E foi Katz que inventou o deflate dos Unix. Compressão é outro tema complicado de explicar a história, mas até hoje você usa alguma variação disso. página na web que o seu navegador baixa é entregue comprimido pelos servidores web normalmente por gzip.

De qualquer forma essa tangente foi só pra explicar que com as ferramentas que eu descrevi você já consegue montar um fluxo de trabalho pra um projeto como a kernel do Linux. O Linus Torvalds fez um tarball da versão 1.0 da kernel e aí coloca num servidor FTP público. Um outro desenvolvido como Alan Cox ou Andrew Morton Baixa do FTP e começa a desenvolver alguma nova funcionalidade. Quando termina faz um diff dos arquivos e envia anexado num email de volta pro Linux.

No Unix e Linux existem comandos de terminal pra conectar em servidores POP3 ou IMAP que a gente usa hoje em dia. Então o Linux consegue automatizar baixar o email, separar o anexo e usar o comando PAT do Linux pra aplicar os PATs na versão na sua máquina. Se tudo estiver ok pra ele, ele faz um novo tarball versão 1.1 e coloca no servidor.

Se você já fuçou servidores de FTP já deve ter visto diretórios de projetos com tarballs de diversas versões. Não é um fluxo eficiente em 2020, mas nos anos 90 a gente tá falando do que havia de mais avançado em fluxo de trabalho distribuído. Então a internet somado com ferramental Linux como Diff, Pet, Tar, Gzip, FTP e Mail permitiram um fluxo de trabalho distribuído.

e o nascimento do mundo open source como conhecimento. Alguma variação disso já existia no mundo Unix nos anos 80, mas foi com o Linux que esse modelo de trabalho começou a ganhar chão. Mas isso é no mundo pós-internet comercial e Linux.

No começo dos anos 70 já havia o conceito de versionamento de código fonte. Em resumo, em 1972 havia o SCSS ou Source Code Control System, desenvolvido na linguagem Snowball na Bell Labs obviamente e usado em sistemas como IBM System 370 até o p... PDP11.

Nos anos 80 foi substituído por uma evolução que foi o RCS ou Revision Control System. O RCS ainda é mantido até hoje. E finalmente por volta, de 1990 surgiu o Concurrent Version System ou CVS pra substituir o RCS.

O modelo sempre foi o que se chama de centralizado ou cliente-servidor, que era a arquitetura da moda dos anos 80 e 90. Você configurava um servidor onde ficava o projeto, na máquina de cada desenvolvedor, você instala um cliente que consegue se conectar nesse servidor. O servidor era responsável por coisas como autenticar o login de cada desenvolvedor pra dar permissão de acesso ao código. Daí o desenvolvedor podia fazer check-out pra baixar todo o código, fazer check-in pra subir as modificações e de tempos em tempos dar um update pra baixar as últimas modificações do servidor. O servidor ia guardando os deltas de modificação, possível graças a idéia de patches. Novas versões adicionaram coisas como Delta Compression pra economizar espaço no disco guardando os patches zipados.

E novas funcionalidades foram aparecendo como a ideia de branches. Branch é um conceito simples, como a operação complicada. Fazer um branch da forma mais grosseira é duplicar o diretório do projeto. Daí você trabalha num diretório separado.

Quando termina gera os patches e aplica no diretório principal. e pode apagar o diretório duplicado. É uma forma de trabalhar numa funcionalidade que pode demorar, ou testar correção de bugs, sem atrapalhar o diretório principal.

Isso funciona bem se você trabalha sozinho, ou com poucas pessoas, ou com pessoas que estão muito bem coordenadas entre si. Caso contrário, isso se torna um puta pesadelo muito rápido. Nos dias de hoje você tem pull requests no GitHub que é basicamente um branch do projeto. Pra adiantar essa história, o que foi o que aconteceu com o Mergel? Subversion de fato nasceu com o conceito de CVS feito direito.

Na prática ele adota um fluxo muito parecido com o CVS mas com uma implementação menos puxadinho e um pouco mais estável. O básico funciona igual, checkout, check-in ou commit e update. Mas branches sempre foi o calcanhar de Achilles.

Subversion consertou branches tarde demais. Só na versão 1.5 que saiu em junho de 2008 que ele ganhou a funcionalidade de Merge Tracking. 8 anos depois da primeira versão. Aí foi muito pouco, muito tarde.

Em 2008 foi quando o GitHub começou a bombar e aí o resto da história. Eu já expliquei porque a gente odeia coisas como source safe. Porque o conceito de bloquear arquivos pra só uma pessoa usar de cada vez é uma desgraça. Pior ainda pra gerenciar releases ou fechar versões.

Era tão complicado essas porcarias que nos anos 90 e começo dos anos 2000 havia a figura de um gestor de configuração. Um cara que tinha um projeto de arquivo que não tinha um código. E aí o que aconteceu?

pago pra fazer o equivalente a commit e taguear a versão. Pensa no absurdo de precisar de alguém tempo integral pra não corromper muito o código fonte. O outro problema eram as branches.

E é a razão principal de porque CVS e Subversion tiveram reputação tão ruim. A gente era meio que obrigado a usar porque não tinha opção melhor. Ninguém usava porque gostava.

Faça um exercício, tenta instalar um servidor CVS em qualquer Linux hoje, é super chato. Eu mesmo perco a paciência e desisto no meio de tão chato que é configurar um CVS. Subversion é um pouco mais fácil de configurar e mesmo assim é um saco. Um dos grandes defeitos estruturais do CVS é que ele guardava revisões por arquivo. Ele não entendia o conceito de um único arquivão de patch de uma funcionalidade inteira como um pull request hoje por exemplo, que é um conjunto de commits.

De forma simplória, um commit é nada mais que um arquivo de patch. patch com um cabeçalho com metadados como o autor do commit e data e hora. Mas enfim, era difícil de gerenciar versões no CVS. Cada desenvolvedor precisava trabalhar num branch ou num fork, que pra todos efeitos e propósitos é mais ou menos a mesma coisa. Uma duplicata do projeto original.

Só que pra combinar as modificações de dezenas de desenvolvedores numa única versão era um curvo job desgraçado. Podia levar um dia inteiro ou mais. pra conseguir fazer esse merge.

Eis que na virada do século surge a Bitmover e seu produto Bitkeeper. Muita gente pensa que a principal diferença era ser descentralizado, mas na realidade a principal novidade foi tornar branches, forks e principalmente merges operações razoavelmente triviais. Um trabalho que podia levar horas ou dias reduzido pra minutos e com muito menos margem de erros.

Por isso que apesar de ser um produto comercial de código fechado, por pragmatismo o Linus resolveu migrar o desenvolvimento do kernel pro BitKeeper. Isso foi em 2002. Mas em dois ou três anos teve o problema que já falei que a BitMover resolveu botar restrições demais ao ponto que o Linus se encheu. Com o CVS e Subversion que eram as alternativas Muito atrasados em relação ao BitKeeper, as outras alternativas comerciais sendo as porcarias que sempre foram, muitos começaram a pensar em novas soluções.

Assim em 2003 surgiu o Darks, em 2005 surgiu o Mercurial e a própria Canonical que mantém o Ubuntu fez o Bazaar. E também em 2005 o próprio Linus resolveu fazer o Git. No papel todos eles são muito parecidos, sistemas de versionamento descentralizados com foco em resolver o problema de branches e merges.

A A diferença é que todos eles tinham problema de performance menos o Git. Mercurial e Bazaar eram feitos em Python, então eles não tem como escalar em performance até certo ponto. Dark, se não me engano, era feito em Haskell e também era criticado por problemas de performance.

O Git por outro lado, feito pelo Linux, sempre foi hiper rápido, porém difícil de usar, mas em casos como esse performance e principalmente segurança tem prioridade. Antes desses novos sistemas, a estrutura de dados que ferramentas como Subversion entendiam era uma árvore. Pense diretórios e arquivos, é uma árvore. Um branch era mais ou menos duplicar a árvore. E um merge era comparar duas árvores.

Pra ilustrar um problema óbvio, pense que no diretório original você renomeia um arquivo e no diretório duplicado você deleta o mesmo arquivo. Agora tenta fazer um merge disso no Subversion ou CVS, você vai tomar um conflito de merge. Isso é o tipo de coisa que um Git faz merge automaticamente e corretamente.

Bitkeeper e os outros novos também. Conflitos de merge é o pesadelo de todo desenvolvedor nesses sistemas antigos e incompetentes. Num Git minimamente bem usado você raramente encontra conflitos.

E mesmo quando encontra eles costumam ser fáceis de resolver. Hoje em dia trabalhar em brands é super comum, a gente faz isso o tempo todo. Fazer merge também. Idealmente você faz merges com frequência e evita deixar código não mergeado esquecido num branch por semanas ou meses. Mas em sistemas antigos fazer branches custava meio caro, e como merges eram complicados você evitava ao máximo fazer com frequência, só que quanto mais você espera, também mais caro vai ficando, então era uma faca de dois gumes.

Em vez de ter que passar por todo esse pesadelo, a maioria simplesmente desistia de fazer brands e todo mundo trabalhava na mesma versão, que em Subversion se chama Trunk. Em Git é o que você conhece como Master. Por isso antigamente se tinha tanta discussão sobre quem podia ou quem não podia ter acesso de escrever, ou seja, acesso de commit nesse trunk.

O Linus explica isso melhor. Uma das coisas muito legais, que também é... Talvez você não tenha essa questão dentro de uma empresa, mas nós certamente temos isso em toda comunidade de open source que eu já vi que usa cvs ou subversão ou algo assim. Você tem essa noção de acesso a comitê. Porque você tem um repositório central, significa que todo mundo que está trabalhando nesse projeto precisa escrever para o repositório central.

O que significa que, como você não quer que todo mundo escreva para o repositório central, porque a maioria das pessoas são moronas, você cria essa classe de pessoas que são ostensamente não moronas. E a maioria das vezes o que acontece é que você faz aquela classe muito pequena, porque é realmente difícil saber se uma pessoa é inteligente ou não. E mesmo quando você faz ela muito pequena, você vai ter problemas.

Então, esse assunto de acesso a comitê, que algumas empresas são capazes de ignorar, mas apenas dando a todos acesso a comitê, é uma grande barreira psicológica e causa horas de política em mais de muitas fontes abertas. projetos. Se você tem um modelo distribuído, ele vai embora.

Todo mundo tem acesso a comitê. Você pode fazer o que quiser para o seu projeto. Você só tem seu próprio branch, você faz trabalho ótimo ou você faz trabalho estúpido.

Ninguém se importa. É sua cópia, é seu branch. E depois, se de fato você fez um bom trabalho, você pode dizer às pessoas, diga às pessoas, aqui está meu branch e, por exemplo, ele se performance 10 vezes mais rápido do que qualquer outro branch.

Então, como se eu fosse a que me empurra? E as pessoas fazem. E é assim que funciona e nunca temos política. Isso não é muito verdade, mas temos outras políticas. Não temos que nos preocupar com a coisa do acesso a comitê.

E eu acho que isso é um grande problema e isso só. Agora, por que branches e merges num sistema como o Git é tão infinitamente melhor do que num subversion antes da versão 1.5? Pra simplificar, vamos pensar o que você vê hoje em dia num projeto no GitHub da vida, que usa Git por baixo. Aliás, se você não sabia, você não precisa de GitHub pra usar Git.

é só um facilitador, mas ele é opcional. De qualquer forma, se você já fez qualquer tutorial de Git e já tentou usar um pouco, deve ter notado alguns termos que a gente usa. Vamos recapitular, você faz git clone pra puxar uma cópia do projeto pra sua máquina. Você vai fazendo modificações, edita um arquivo, cria um novo, renomeia outro, e quando termina uma parte do trabalho faz um git add pra marcar essas alterações e um git commit pra empacotar essas modificações.

Se você não O git commit por baixo faz algo equivalente ao diff que eu falei antes. Um commit é o patch de modificações desde o commit anterior. Eu fiz o episódio de criptografia básica porque eu precisava ensinar um conceito lá que eu vou usar agora.

Uma das coisas que o Linus queria garantir é que os dados no repositório git sejam sempre confiáveis, ou seja, que eu possa confiar que o texto que eu baixo dele tá sempre correto. Pra garantir isso. A próxima coisa depois do tal diff que o git commit faz é passar o patch por um algoritmo de hashing, no caso o sha1.

Esse é aquele numeruzão longo e estranho que todo commit tem, é o hash do patch, a assinatura daquele delta. Lembra do conceito de hash? Se eu modificar um bit dentro desse patch, o sha1 vai mudar completamente e não vai mais bater com o sha1 original, então eu sei que o patch tá corrompido.

E aqui vale mais uma curiosidade, eu não entendo quando as pessoas Gita, que tutorial de Git eu devo estudar? Qual é a dificuldade de ler a documentação no site oficial das coisas como primeiro passo? Eu sempre achei óbvio ir no site oficial de tudo que eu quero aprender.

Se você tivesse ido no site do Git e aberto o link Book que é o livro e lido o capítulo Git Internals já saberia muito do que eu estou dizendo aqui. Só pra não perder tempo, eu vou justamente usar um trecho desse capítulo. Eu disse que não vou fazer um tutorial, mas eu acho interessante demonstrar que eu não sei o que é o tutorial.

algumas coisas nesse ponto. Eu fico bastante irritado de ver programadores usando ferramentas que geram arquivos e modificam coisas no seu projeto e ele não sabe o que está acontecendo. Deixa eu fazer outra tangente. Quando eu aprendi CVS, uma coisa que era necessário pra ferramenta rastrear os arquivos é que ele sujava todo meu projeto criando diretório.cvs em todos os subdiretórios do projeto.

Era um saco isso. Esse subdiretório começa com um p... ponto porque todo mundo sabe que em Linux um arquivo que começa com ponto significa escondido.

Se você mexesse nesses diretórios, tinha muita chance de estragar tudo e ter que dar um check out de novo pra reconstruir certo. Subversion fazia a mesma coisa, só que agora eram subdiretórios.svn. Até aí tudo bem, só que em 2003 eu desenvolvia em Windows e tinha projetos.NET que eu precisava usar Visual Studio.

Se você usasse alguma coisa como a porcaria do Source Safe, tecnicamente tudo funcionava integrado. Mas obviamente eu era rebelde e queria usar Subversion pra tudo. Pois bem, me fudi. Visual Studio crasheava quando tentava abrir um projeto vindo do Subversion, porque em 2003 nem Windows XP...

nem Windows Server 2003 entendiam direito arquivos que começavam com ponto. Era um dos motivos de porque quase ninguém usava Subversion com projetos de Visual Studio no começo dos anos 2000. E o que eu fiz? A ferramenta que normalmente se usava pra dar checkout de repositórios Subversion se chamava Tortoise SVN. Era uma ferramentinha feita em Visual C++.

Então eu fiz um patch pra esse projeto, eu fiz o Tortoise criar esses subdiretórios de rastreamento como underline-svn em vez de.svn. E aí o Visual Studio conseguia abrir o diretório, agora sem crashear. Pra fazer isso, primeiro eu precisava saber que não tinha importância renomear esse diretório, porque ele só era importante pro cliente do Subversion, não pro servidor.

Hoje em dia, felizmente o Windows já entende arquivos e diretórios que começam com ponto, porque o Git faz a mesma coisa. Ele cria um diretório chamado.git, mas ele é diferente do CVS e Subversion porque na realidade agora os arquivos e diretórios do projeto que você vê e edita aqui não tem importância. O conteúdo de verdade dos arquivos fica no repositório dentro desse.git e por isso só tem um na raiz e não em todos os subdiretórios.

Entenda, se você cria um projeto qualquer, digamos de Node, C Sharp, tanto faz, e dá.git e.nit pra iniciar. Depois git add de tudo e o primeiro git commit. Agora você pode apagar os arquivos originais Menos o diretório.git. Mesmo se você apagar qualquer arquivo, qualquer um pode ser recuperado com um simples git checkout.

Ele vai procurar o arquivo dentro desse.git, sem precisar perguntar nada pra nenhum servidor. É por isso que você consegue ficar mudando de branches no mesmo diretório, o conteúdo inteiro muda, arquivo some e reaparece. No Mercurial toda nova branch gera um novo subdiretório, um novo diretório ao lado do diretório original do projeto.

Só que se você listar o que tem dentro desse diretório, você não vai achar os arquivos do seu projeto. Em vez disso, vai ter alguns subdiretórios meio estranhos e um maior que é o.git barra objects. E nele vai achar um monte de arquivos com nomes que parecem hashes de SHA1.

Ficou complicado? Deixa eu ilustrar. Nessa parte eu vou seguir igualzinho a primeira página do capítulo de Git internos do livro gratuito que tá no site oficial, que é uma coisa que você já devia ter feito também.

Vamos lá. Primeiro criar um novo repositório local de Git com o comando git init test. Agora vamos listar o tal diretório.git barra object.

Vazio. Agora vamos usar um comando que você nunca viu, o git hash object. Vou dar echo de uma string e passar pra esse comando.

Agora se listar de novo o diretório você vai ver que apareceu um arquivo lá com o nome sendo o shaun desse string. Agora pra pegar o conteúdo desse arquivo podemos usar outro comando que você nunca viu. e nem nunca vai usar, o git cat file.

E pronto, é o conteúdo que passamos antes. O repositório git é um banco de dados de objetos. Vamos dar echo de um string qualquer pra dentro de um arquivo.

Isso é uma operação do sistema operacional, nada a ver com git. Agora vamos usar o git pra gerar o hash do conteúdo do arquivo com o git hash object de novo. Faltou nesse livro apagar o arquivo original antes de dar echo de novo, senão o próximo comando vai falhar.

Então vamos apagar. e agora dá eco de um novo conteúdo com o mesmo nome de arquivo. Rodamos hashObject e obviamente o SHA1 tem que ser diferente pra um conteúdo diferente.

Listando os objetos agora, temos mais arquivos. Nesse ponto podemos apagar de novo o arquivo e recuperar o conteúdo que tá no arquivo racheado. E assim sabemos que é possível recuperar conteúdo que você apagou a partir do versionamento do repositório. É assim que comandos como o git checkout funcionam. Só que até aqui a gente está gravando meramente os conteúdos dos arquivos mas não os metadados, como o nome do arquivo, estrutura de diretório ou atributos.

Os objetos que criamos até aqui são meros blobs, um punhado de bytes. Pra organizar precisamos criar esses metadados que também são objetos, mas em vez de tipo blob eles são tipo tree ou árvore. Pra isso precisamos usar uma área intermediária do Git onde é possível manipular esses metadados. Se você já usou o comando git add, é nessa área intermediária que o git estaciona suas modificações.

No nosso caso, queremos adicionar os metadados na primeira versão do arquivo text.txt que criamos no começo. Então vamos usar outro comando que você nunca viu, o git update index, e esse número 1644 é o mode do arquivo, que se você já usou Linux antes deve saber do comando ch que é changeMode. 644 é um arquivo normal, 755 é um arquivo executável. Ou sendo mais exato, o primeiro número é um modo pro usuário dono do arquivo, o segundo número é um modo pro grupo, e o terceiro número é um modo pra qualquer outro usuário.

7 é ler, escrever e executar, 5 é ler e executar, 4 é só leitura e assim por diante. Estude sobre chmod depois pra entender isso melhor, é coisa básica de Linux. De qualquer forma, Nada foi gravado ainda.

Pra gravar precisamos agora tirar da área estacionada ou stage com o comando git write tree. Agora criamos um novo objeto de tipo tree com os metadados e podemos usar o git catchfile pra ver. Agora vamos criar um novo objeto de tree só que apontando pra dois outros objetos, um novo arquivo e um que já existe. Primeiro criamos o arquivo new.txt, agora damos update index na versão mais recente do teste txt que criamos antes e e também um update index no arquivo new txt. De novo estamos trabalhando na área intermediária de staging, então quando terminamos de adicionar os metadados, agora podemos fazer git write tree pra gerar o objeto de tree com esses metadados.

Vamos listar com cat file e agora ele mostra os dois blobs que esse novo objeto de tree está apontando. Vocês entenderam o que estamos fazendo? A gente está manipulando o repositório git local que é basicamente um banco de dados de objetos..

criando esses objetos e apontando novos objetos de metadados pra eles. Até agora nossa estrutura tá mais ou menos como nessa ilustração. Finalmente vamos pro terceiro tipo de objeto interessante aqui, os commits.

Vamos criar um commit apontando pro último objeto de Quando tentamos criar um commit o Git vai reclamar que eu ainda não configurei e-mail nem nome pra etiquetar no commit. Pra gerar os mesmos shaun do exemplo eu vou usar o e-mail e nome do Scott Chacon que é o autor desse livro e um dos sócios fundadores do GitHub. Mas na sua máquina você deve usar seu próprio nome e e-mail, claro.

Pronto, agora geramos o commit de novo e novamente ele nos devolve um hash. Veja como tu todo objeto, seja um blob, um tree, um commit ou qualquer outro tipo, sempre gera um shaun que ao mesmo tempo serve como ID desse objeto e também como um validador da integridade do dado. Podemos usar o mesmo cat file pra mostrar esse commit também usando o hash que acabamos de gerar, e se você já usou Git antes, esse formato deve ser familiar pra você.

Vamos gerar mais dois objetos de commit, cada um referenciando o commit anterior. Então criamos o segundo commit apontando pro primeiro e o terceiro apontando pro segundo. E agora, se usarmos o comando git log, vamos ver tudo organizado.

Entenda o que aconteceu até aqui. Usamos comandos de baixo nível do git, que são conhecidos como plumbing ou encanamento mesmo, como cat file, write tree, update index, cache tree. pra fazer as mesmas coisas que outros dois comandos que você talvez já conheça, o git add e git commit.

Add e commit são comandos conhecidos como porcelain, de alto nível. Todo tutorial e curso de git só ensina os comandos porcelain, mas entenda que por baixo dos panos, na realidade esses comandos fazem uso do encanamento, dos comandos plumbin, que você raramente vai usar. O Linux desenvolveu primeiro os comandos plumbin, Foi depois que o Junior Ramano entrou como novo mantenedor que ele e outros colaboradores foram melhorando a usabilidade e criando comandos mais simples pra meros mortais. Agora vamos terminar essa parte mostrando por outra perspectiva.

Vamos abrir o console de Ruby puro. Começamos criando uma variável com uma string. Agora vamos criar uma variável chamada header, que tem como conteúdo a palavra blob.

Vamos criar uma variável chamada header. e o tamanho da variável anterior. Finalmente vamos criar uma terceira variável chamada store que é o header mais o conteúdo. Vamos importar a biblioteca de sha1 do Ruby e gerar a versão hexadecimal de 40 caracteres desse store. Agora vamos abrir um outro terminal e usar o primeiro comando plumbing do Git que vimos, o hash object.

E veja que o sha1 é exatamente igual. É assim que o Git estrutura o conteúdo e gera o hash. Se você for até deve ter notado que usamos o comando git catch file pra ver o conteúdo do arquivo, mas porque a gente não usa o comando catch padrão do Linux? Vamos fazer isso no terminal.

E veja que apareceu só um monte de sujeira que não dá pra ler. É um binário, não um texto. Mas o que é esse binário? Voltando pro Ruby, vamos importar outra biblioteca, a zlib, pra ter acesso ao método deflate.

Lembram que eu falei de deflate antes, que é a compressão do gzip? Então vamos aplicar deflate na variável store e esse é o binário comprimido da string original. Parece maior porque é a representação do binário no terminal, mas o conteúdo real é menor.

E pra simular o que o git hash object faz, vamos gravar o arquivo. Primeiro vamos gerar o caminho completo do diretório e arquivo. De curiosidade você vai notar que quebramos os dois primeiros caracteres desse SHA-1 pra fazer um subdiretório e colocamos o restante como nome do arquivo dentro dele.

Se você é um pouco experiente entende porquê. Entenda que diretórios tem limite de arquivos, eu não lembro se eram 64 mil arquivos. Pra evitar ficar tudo num diretório só, criando subdiretórios a partir do SHA-1, eu não...

vai ajudar a balancear os arquivos. Agora você pode ter uns 64 mil subdiretórios, cada um com 64 mil arquivos, ou seja, aumentamos a capacidade máxima pra uns 4 bilhões de arquivos. Acho que deve ser suficiente. Agora vamos importar a biblioteca fileutils pra criar os subdiretórios caso não existam. No Linux usamos o comando mkdir com o número traço p pra isso.

Por isso o método no fileutils do Ruby se chama mkdir. Underline p e finalmente gravamos a versão comprimida do conteúdo no novo arquivo. Pra ver se funcionou podemos sair do console do Ruby e usar o mesmo comando git cat file pra abrir esse objeto blob que acabamos de criar e funciona.

Repetindo, quando você clona um projeto do GitHub pra sua máquina, os diretórios e arquivos do projeto que você vê no seu editor são só um espelho do que está dentro do diretório.git barra objects. O banco de dados de verdade são esses objects. A estrutura de diretórios e arquivos pode ser inteira recriada a partir desses objetos. Mais do que isso, perceberam que quando criamos o SHA-1, ele só conseguia... Depois dera o blob.

Os metadados como nome do arquivo e diretório ficam num objeto separado do tipo tree. É uma das razões de porque o Git é mais eficiente pra comparar versões diferentes. Lembra quando eu falei da situação de você renomear um arquivo num branch e apagar o arquivo no outro branch e o conflito que isso dá no Subversion ou CVS?

No Git esse conflito não existe. O Git rastreia primeiro o conteúdo, depois os metadados. Mas essa é só a primeira vantagem.. E com esse exemplo de Ruby você sabe como as bibliotecas de Git em qualquer outra linguagem se integram com repositórios Git. É isso que permite um GitHub ou GitLab.

A estrutura de dados do Git é aberta e razoavelmente simples de trabalhar. Eu recomendo que vocês leiam o livro no site oficial do Git pra entender como o resto do Git funciona. Mas agora eu posso voltar pro problema principal. Branches e Merge.

Como eu disse antes, imagine que em sistemas antigos tipo CVS um branch é mais ou menos internamente como duplicar o diretório inteiro do projeto. E o merge é fazer diff no diretório duplicado, gerar os patches de cada arquivo e aplicar de volta no diretório original. Parece simples, mas é muito fácil de ver como isso vai fracassar homericamente.

Esse tipo de merge é o que se chama de two-way. O Git prioriza. não a estrutura de diretórios, mas um grafo, mais especificamente um DAG ou um Direct Acyclic Graph.

Acíclico porque os nós desse grafo não apontam de volta um pro outro causando um loop infinito. Vocês viram como manualmente criamos um commit novo apontando pro commit anterior, é isso que o comando git commit sempre faz, cria um commit ligado ao anterior, criando uma cadeia. O DAG é esse grafo de commits.

Um branch é nada mais nada menos que um desvio nesse grafo com uma etiqueta com o nome do branch. A vantagem disso é que todo branch tem a informação do ponto de origem, a partir de qual commit começa o branch. Um CVS e o Subversion antes da versão 1.5 não tem essa informação. Depois que você faz o merge uma vez fudeu, você não pode mais continuar trabalhando no branch porque o próximo merge vai ser um inferno na terra de conflitos.

Até aqui deve estar meio confuso pra vocês visualizarem, então vamos fazer um pequeno exemplo. Na verdade eu adaptei o exemplo de um artigo da revista Dr. Dobbs que eu li em 2013 pra entender isso e ainda é um bom exemplo, então eu deixo o link nas descrições abaixo. Pra variar, vamos chamar nossos desenvolvedores fictícios de Alice e Bob.

Cada um tem uma cópia do projeto. Em um determinado momento precisamos mergear o trabalho dos dois. Você abre o arquivo da Alice e encontra o comando print hello na linha 30. Daí abre o mesmo arquivo do Bob e vê o comando um pouco diferente, print by na mesma linha 30. E agora? Um CVS olha pra esses dois arquivos e tem que interromper o processo de merge porque ele não tem como decidir qual das duas linhas é válida.

Agora a Alice e o Bob precisam ser chamados pra ver se eles lembram qual era o correto. Isso é um pequeno exemplo, agora imagina isso acontecendo em centenas de linhas de dezenas de arquivos no mesmo projeto. Isso é o que chamamos de um merge two-way, ou seja, com duas versões sendo comparadas. A diferença no Git é que quando fazemos um branch ele marca o commit de origem do branch. Agora Alice continua trabalhando no branch original master e o Bob começa a trabalhar no novo branch, digamos hotfix, que acabamos de criar.

Mesma situação, no final precisamos mesclar o trabalho dos dois e chegamos no mesmo problema de antes na tal linha 30 do arquivo. A diferença é que o Git pode voltar no passado até o ponto onde o branch foi criado e olhar como era o arquivo original. Agora a gente tem 3 bases de comparação, a versão da Alice, a versão do Bob e a versão original. E se olharmos a versão original vamos descobrir que originalmente a linha 30 tinha o comando printby. Então quem modificou o arquivo foi a Alice, e o Git pode escolher automaticamente usar a versão mais recente, que é certamente a da Alice.

E o processo de merge não dá mais esse conflito e pode seguir automaticamente. Branching em subversão é uma operação O1. Você pode fazer o quanto mais baratos você quiser.

Não se preocupe que o O1 é realmente bastante grande, eu acho. Mas, mesmo se demorar um milhão de segundos para fazer branching, quem se importa? É a coisa errada que você está medindo.

Ninguém está interessado em branching. Branches são completamente inúteis, a menos que você merge. e o CVS não pode mergir nada de novo.

Você pode mergir coisas uma vez, mas porque o CVS esquece o que você fez, você nunca pode mergir nada de novo, sem ter conflitos horríveis. Mergir em subversão é um desastre completo. As pessoas de subversão acreditam nisso e têm um plano, e o seu plano também é ruim.

É incrível o quão estúpido essas pessoas são. Eles estão olhando para o problema errado o tempo todo. Branching não é o problema, é mergir.

E mergir eles não fizeram squat, cinco anos depois do fato. Isso é triste. Então, a performance é importante, mas você precisa olhar para o que importa.

Performance para fazer um branching no Git. É literalmente você criar um novo arquivo que tem 41 bytes de tamanho. Quanto rápido você acha que é? Eu não acho que você pode medir. Você pode...

Se você usa Windows, você provavelmente pode medir porque o arquivo... Mas, seja o que for, é tão rápido que você não consegue realmente medir. Isso é criar um branch.

Ninguém se importa. Não é um problema. Não é isso. A única coisa que importa é quão rápido você pode mergear.

No Git, você pode mergear. Eu mergei 22 mil arquivos, várias vezes por dia. E eu fico desagradável se um merge demora mais de cinco segundos e todos esses cinco segundos são apenas o download dos Diffs.

Não os Diffs, mas os Deltas entre os dois 3. O Merge em si, leva menos de 0,5s. O que leva mais tempo do que o Merge é, depois de cada Merge, de forma de default, o Git vai fazer um DiffStat de tudo o que mudou como resultado desse Merge, porque eu me importo com isso. Quando eu Merge com alguém, eu confio neles, mas, por outro lado, eles poderiam ter parado de usar a medicina. Então, eu confio neles, mas, vamos ser honestos aqui, eles poderiam ter sido ok ontem.

Hoje não é um bom dia. Então eu faço um DiffStat e Git faz isso de forma de default, você pode desligar se você realmente quiser, mas você provavelmente não deveria, é rápido o mesmo jeito. O DiffStat normalmente toma, se é um grande merge, o DiffStat normalmente toma um segundo ou dois, porque criar um Diff e realmente fazer todas as estatísticas sobre quantas linhas mudaram, isso realmente é muito mais caro do que fazer o merge em si. Essa é a forma de performance que realmente muda como você trabalha.

Agora você começa a entender porque o algoritmo de Merge 3-way é absurdamente superior a 2-way. Por causa disso o Git consegue eliminar praticamente todo o conflito que daria num CVS. Esse foi o ponto que pra mim mais me deixou impressionado em 2007. Mais do que isso, depois que o Git conclui o merge ele cria um commit de merge.

Agora Alice e Bob podem continuar trabalhando cada um em seu respectivo branch e quando forem fazer um novo merge, o novo ancestral de comparação vai ser esse último merge e não o commit de quando o branch foi criado. Num CVS e no Subversion sem o Merge Tracking da versão 1.5 que eu falei, eles não tem como saber quando acontecer o último merge e ele sempre vai comparar tudo de um branch contra tudo do outro branch. Então se da primeira vez deu um monte de conflito, vai dar tudo de novo no próximo merge e só vai piorando.

Hoje em dia se você só usou Git e ocasionalmente fez alguma besteira e deu alguns conflitos no merge é só isso, um pequeno inconveniente. Mas antes de ferramentas como Git era o que eu falei antes, um verdadeiro inferno na Terra. Como anedota, Quando eu era consultor Java e SAP, eu tava num cliente com minha equipe.

Um dos desenvolvedores, amigo meu, fazia faculdade a noite. E ele era do tipo que se irritava com as coisas mesmo. Ele tava atrasado e deu um tanto de conflito quando ele deu um update ou commit, não lembro.

Ele tentava resolver os conflitos e não ia. No fim ele saiu atrasado pra faculdade a noite, puto da vida, e bateu o carro. Então Subversion já fez alguém bater o carro. Não estou exagerando, era assim ruim. Então quando eu ouvi o Torvutz xingando o povo do Subversion, eu sabia exatamente do que ele tava falando.

Sério, no marketing do Subversion, onde eles falavam que era CVS feito direito, também tinha bastante propaganda de como criar branches era uma coisa simples no Subversion. Isso era totalmente irrelevante. De fato, criar branches no CVS era um pouco mais custoso.

Mas o problema nunca foi criar branches, o problema sempre foi mergear a porcaria dos branches. E isso o Subversion levou 8 anos pra remendar. Depois dessa Tectalk do Torvalds, ainda levou mais de um ano pra adicionar o maldito Merge Tracking. Mas nesse ponto já era tarde demais, eu já tinha abandonado o Subversion e comecei a usar a Git.

Mas tinha um problema. Ao meu redor só eu queria usar Git pra variar. Quando eu deixei de ser consultor SAP e virei freelancer de Ruby on Rails, os primeiros projetos que eu peguei ainda eram em Subversion.

Felizmente tanto Mercurial quanto Git tinham um adaptador. Era possível fazer checkout, baixar o código de um repositório Subversion, converter localmente em um repositório Git e trabalhar normalmente com Git. Depois que eu tivesse terminado de mergear meus brands e tivesse tudo pronto, dava pra dar commit de volta pro repositório Subversion, então era possível começar a migrar minha forma de trabalhar mesmo se o cliente não quisesse mudar pra Git.

Essa é a outra vantagem de sistemas distribuídos. Num sistema centralizado, qualquer coisa que você precisa fazer, precisa pedir pro servidor. Então se eu tivesse offline, digamos num aeroporto, e eu quisesse fazer um commit pra não perder acidentalmente o que eu tava fazendo, não tinha como, porque em Subversion, commit é é o equivalente a commit e push do Git, ele precisa enviar pro servidor, mas offline já era, meu fluxo de trabalho era interrompido. Compare com hoje em dia, 2 anos atrás eu realmente fui codando um projeto durante meu voo pra Las Vegas, fiquei as 8 horas do voo codando, e fazendo tudo o que eu precisava.

Quando cheguei no aeroporto em Las Vegas, eu conectei meu notebook no 4G e fiz um push pro repositório no meu GitLab. Aliás vale explicar outra coisa. Eu já disse antes que GitHub ou GitLab são opcionais pra usar Git.

Quando você faz um git init, como eu já mostrei, o diretório.git tem tudo que você precisa. Digamos que estamos na situação do aeroporto ou na situação de eu estar em alguma conferência sem internet. Eu já disse isso.

um amigo meu se oferece pra me ajudar num projeto. Como ele clona o projeto de mim? De várias maneiras.

Ele pode se conectar via SSH no meu notebook, ele pode simplesmente pegar uma cópia do diretório pela rede local ou eu posso copiar o repositório num pendrive e dar pra ele. Muita gente não sabe disso, mas quando você faz um git clone de um GitHub, a diferença pra um repositório criado localmente é só algumas linhas no arquivo de config no diretório.git apontando pra um remote chamado.git. uma origem pra um endereço na internet, que pode ser um servidor https ou mesmo um servidor ssh.

Ou nem precisa ser um servidor, pode ser um outro diretório local na mesma máquina, isso mesmo, você pode fazer git clone de um diretório. Deixa eu mostrar isso. Vamos pegar o repositório que a gente criou antes chamado test, agora vamos sair do diretório. E agora a gente pode fazer git clone desse repositório e chamar o clone de test2. Pronto, tá clonado.

Se... Se a gente olhar o arquivo de configuração do teste 2, vemos uma configuração de remote origin apontando pro diretório em vez do GitHub por exemplo. E como remote é só um texto de configuração, a gente pode apontar pra onde a gente quiser depois.

Git e outros sistemas distribuídos tem como característica não precisar de um servidor central que controla tudo. Como hoje já tá comprido demais esse episódio, um dia eu retomo o assunto, mas... Basta dizer que a forma como todo mundo usa Git via GitHub hoje é só uma das formas de se trabalhar, que provavelmente funciona melhor pra maioria das pessoas mas não é adequada pro fluxo de trabalho dos desenvolvedores do projeto da Kernel do Linux por exemplo, por isso que eles não estão no GitHub apesar de usar Git. Eu mesmo prefiro que terceiros não tenham acesso ao meu código fonte e nem dos meus clientes, por isso eu mantenho uma instalação privada de GitLab.

Tudo funciona igualzinho ao GitHub, se não melhor em muitos casos. E mesmo sem GitLab, pra casos menores bastaria fazer o que eu já fazia 10 anos atrás, dar git init num servidor de SSH e todos os meus amigos podem clonar de lá e a gente já pode trabalhar. Uma das grandes barreiras que o Git enfrentou desde o começo, principalmente comparado com a concorrência, é que ele foi feito pra ser usado num terminal Linux. O Git é um conjunto de programas de linha de comando que que assume que tá num ambiente POSIX, portanto em Windows sempre foi bem chatinho de usar porque o comando prompt sempre foi uma grande porcaria e o suporte POSIX sempre foi meia boca, o que uma década não faz. Se você assistiu meu vídeo sobre Windows Subsystem for Linux ou WSL, agora o Windows oferece um terminal decente e agora tá super fácil usar programas de linha de comando de Linux nativamente no Windows.

Pra isso, diversas IDEs em editores de texto incluindo o Visual Studio Code tem suporte decente de Git também. Então mesmo no Windows você consegue usar Git sem grandes problemas hoje. Em 2008 quando eu fui trabalhar na LocaWeb, assim como muitas outras empresas, eles usavam o que? O famigerado e odiado Source Safe da Microsoft. E eu, do meu jeito delicado de chegar chutando a porta, forcei a migração de todos os projetos e códigos fonte da empresa pra ficar num servidor Git.

Na época GitHub ainda tava só começando. nem existia, mas havia um projeto open source chamado Gitorious que dava suporte somente a hospedar projetos open source. Como o código era aberto, eu adicionei a funcionalidade de administração e gerenciamento de usuários e permissões, e foi isso que a gente usou por muito tempo.

Depois que eu saí eles migraram pro GitLab que tinha acabado de lançar e é bem melhor. Eu lembro que a rejeição ao Git era muito grande, especialmente por conta desse suporte ruim a a usar em Windows pelo command prompt. Eu literalmente fui sentando na mesa de cada desenvolvedor pra ensinar a usar os comandos e fluxos básicos. Foi uma puta dor de cabeça na época, só um louco pra me deixar fazer isso em 2008. Levou meses até todo mundo se acostumar, mas eu acho que valeu a pena.

Por causa de todas as limitações e a filosofia de servidor centralizado em corporações antiquadas, o mais comum ainda é esconder o máximo do código fonte possível. Normalmente desenvolvedores de departamentos diferentes não têm acesso ao código de outros departamentos. Hoje em dia, em ambientes modernos isso pode parecer um absurdo, mas esse era o normal. Como era fácil fazer merda, era melhor limitar o acesso o máximo possível.

Além de forçar a migração do source safe pra Guitorius em 2008, eu também injetei o conceito de todo mundo ver tudo, todo código fonte fica aberto a todo funcionário. E qualquer um pode criar branches e forks e colaborar via o equivalente a pull requests da época. É o modelo que eu acho que é o mais correto até hoje.

Esconder código garante que código ruim sobreviva mais do que devia, além de criar politicagem desnecessária. E estamos chegando ao fim desse episódio. Como eu falei no começo do vídeo, o objetivo de hoje não era fazer tutorial.

O próprio Linus tem a mesma resposta que eu sempre uso. Eu não estou tentando ensinar vocês como usar Git. panorama de porque o git existe, quais eram as alternativas, porque nenhuma outra foi bem sucedida e o que tem de bom.

torna Git tão diferente do resto. O próprio BitKeeper ainda existe e hoje em dia se integra com Git. A Microsoft ainda tem o Team Foundation Server ou TFS que pra todos os efeitos e propósitos é o sucessor espiritual do Source Safe e eu espero nunca esbarrar em um.

E o TFS também, se não me engano, tem alguma forma de interfacear com repositórios Git. Graças ao GitHub, rapidamente todo mundo migrou pra Git, hoje em dia ninguém mais questiona. E eu espero que vocês tenham aprendido um pouco mais sobre essa que é provavelmente a ferramenta mais básica pra qualquer desenvolvedor hoje em dia. Minha expectativa de vida como desenvolvedor melhorou substancialmente depois que migrei pra Git em 2007. Se tiverem interesse de ver o que eu falava sobre o assunto, vou deixar linkados os posts do meu blog que postei naquela época também.

Se curtiram o vídeo, deixem o joinha, assinem o canal e não deixem de clicar no sininho pra não perder os próximos episódios. Agora eu acho que devo voltar a publicar tudo. toda semana se nada der errado. Então a gente se vê, até mais!