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. 😉