Pare de usar ‘branch’ nos seus Podfiles!

Com certeza se você já usou Cocoapods, em algum momento usou também um pod apontando pra uma branch, como nesse exemplo:

pod ‘MeuPod’, :git => ‘https://meugit.com/meugrupo/meurepo.git’, :branch => ‘minha-branch’  

Ok, até aí, nada fora do normal. Pra quê tanto alarde então?

O problema está em alguns processos internos do Cocoapods.

O que rola nos bastidores?

Quando ele vai fazer o download de uma depedência que aponta para um git, ele executa o seguinte código:

Basicamente, ele faz o clone do repo, e se o usuário passou um commit, ele vai fazer o checkout do commit.

Mas como esse clone é feito? Vamos ver.

Git clone (o quê?)

O cocoapods monta os argumentos do clone com base em alguns critérios. É meio obscuro como ele faz isso, mas com o código fonte dá pra ter uma boa ideia do que rola por trás das cortinas.

Vou fazer um resumo aqui do que essa função faz:

  • Cria os argumentos padrões do clone, com a url, o local onde será clonado e o template vazio.
  • Se for uma shadow clone (que por padrão é, a menos que o cocoapods identifique que o repo não dá suporte), E NÃO FOR USADA A OPÇÃO POR COMMIT, ele baixa somente a branch e pega um depth de 1, que vai pegar só o código “de superfície”, sem puxar histórico e nada mais que o repo armazena.
  • E se não for pra forçar o HEAD (que por padrão não é), ele vai verificar se foi especificada uma tag ou branch, e passa essa branch pro comando.
  • A função retorna os argumentos e o git clone é executado.

Até aí, tudo perfeito certo? MAIS OU MENOS…

Repare o seguinte: quando você especifica um commit, ele vai simplesmente fazer um clone COMPLETO do seu repo, e em seguida fazer um checkout do hash do commit. Não é o mais performático, mas faz um certo sentido.

Alguns repos são gigantescos, pois vão armazenando muito histórico com o passar do tempo, e não é de se admirar se você pegar repos simples antigos com mais de 1GB de tamanho.

Aí o bicho pega: já pensou ter que baixar 1GB ou mais na hora de fazer um pod install, estando numa internet capenga, ou se você tiver limite de dados pra download?

Ahhhh, mas a gente tá tranquilo. Não usamos commit, passamos uma branch pra ele, então vai ser tranquilo.

Bom, é aí que você se engana, e garanto, vai se surpreender!!

Eu juro, não fui eu! Foi ele!! (Cocoapods, seu safado!)

Antes de apontarmos de quem é a culpa, vamos ver o código? O que o cocoapods faz com as opções que você passa pra ele?

Bom, é aqui que eu te deixo com a surpresinha…

Você sabe o que faz esse ls-remote? Quer saber? Veja!!

> git ls-remote https://meugit.com/meugrupo/meurepo.git minha-branch
cf1a476f6b4f6e75b4e2d4cefcd2389aec56f9bf              refs/heads/minha-branch

Ele pega a sua branch e… RETORNA UM HASH DE COMMIT!

Exato! O cocoapods vai transformar sua branch num commit.

E VAI APAGAR A SUA BRANCH DAS OPÇÕES!

Olha que bacana! 🤡

Agora lembra o que ele faz quando você passa um commit??? Isso mesmo!!!

ELE CLONA O REPO COMPLETO!!! 🤬🤬🤬🤬🤬

Me salva! Por favor!! 😭

Apesar da dor de cabeça, a solução é bem simples. USEM TAG!

Quando você precisar apontar pra um git, use tag ao invés de branch. O cocoapods não irá converter sua tag em commit, e irá pegar o depth 1 no momento do clone, tornando o download infinitamente mais rápido.

pod ‘MeuPod’, :git => ‘https://meugit.com/meugrupo/meurepo.git’, :branch => ‘minha-branch’
pod ‘MeuPod’, :git => ‘https://meugit.com/meugrupo/meurepo.git’, :tag => ‘minha-branch’

Não precisa necessariamente criar uma tag, apenas trocar a palavra branch por tag no Podfile. Ele não irá verificar se sua tag é realmente uma tag, e vai pegar na forma de branch de todo modo.

Se ele pode te enganar, você também pode enganar ele! 😈

Existe um motivo pra isso tudo

O cocoapods não faz isso tudo por “maldade” e nem por uma falha de conceito. Na verdade, isso é importante quando o dev está trabalhando com pods em desenvolvimento.

Quando você faz um pod install, apontando pra uma branch, ele pega e converte sua branch num commit, e grava esse commit no Podfile.lock.

Dessa forma, caso novas coisas sejam adicionadas na branch (já que ela está em desenvolvimento), isso não irá impactar no pod install, a menos que o dev use um pod update (o que é o mais natural). Não é o caso da tag, uma vez que a tag não é um código em desenvolvimento.

Por isso, não xingue a ferramenta, mas aproveita que tem uma alternativa aí dando sopa, e se você não precisa desses locks de commit, use sem restrições. 😉