Chapters ▾ 2nd Edition

10.8 Git Internals (Por Dentro do Git) - Variáveis de Ambiente

Variáveis de Ambiente

O Git sempre roda dentro de um shell bash e utiliza uma série de variáveis de ambiente do shell para determinar como ele se comporta. Ocasionalmente, é útil saber quais são essas variáveis e como elas podem ser usadas para fazer com que o Git se comporte da maneira que você deseja. Esta não é uma lista exaustiva de todas as variáveis de ambiente às quais o Git presta atenção, mas nós cobriremos as mais úteis.

Comportamento Global

Algumas partes do comportamento geral do Git enquanto programa de computador dependem das variáveis de ambiente.

GIT_EXEC_PATH determina onde o Git procura pelos seus subprogramas (como git-commit, git-diff, e outros). Você pode verificar a configuração atual rodando git --exec-path.

HOME não é usualmente considerada como customizável (muitas outras coisas dependem dela), mas é onde o Git procura pelo arquivo global de configurações. Se você quiser uma instalação do Git verdadeiramente portátil, completa com as configurações globais, você pode sobrescrever a HOME no perfil de shell do Git portátil.

PREFIX é similar, mas serve para as configurações de todo o sistema (system-wide). O Git procura por este arquivo no caminho $PREFIX/etc/gitconfig.

GIT_CONFIG_NOSYSTEM, se definido, desabilita o uso do arquivo de configurações de todo o sistema. Isto é útil se a configuração do seu sistema estiver interferindo com os seus comandos, mas você não tem o acesso para alterá-la ou removê-la.

GIT_PAGER controla o programa utilizado para exibir a saída de múltiplas páginas na linha de comando. Se isto não estiver definido, a PAGER será utilizada como alternativa (fallback).

GIT_EDITOR é o editor que o Git iniciará quando o usuário precisar editar algum texto (uma mensagem de commit, por exemplo). Se não for definido, o EDITOR será usado.

Localizações de Repositórios

O Git utiliza várias variáveis de ambiente para determinar como ele irá se comunicar com o repositório atual.

GIT_DIR é a localização da pasta .git. Se isto não for especificado, o Git irá subir pela árvore de diretórios até atingir o ~ ou /, procurando por um diretório .git em cada passo.

GIT_CEILING_DIRECTORIES controla o comportamento de busca por um diretório .git. Se você acessar diretórios que demoram a carregar (tais como aqueles em drives de fita, ou através de uma conexão de rede lenta), você talvez queira que o Git pare de tentar mais cedo do que ele tentaria normalmente, especialmente se o Git for invocado ao carregar o prompt do seu shell.

GIT_WORK_TREE é a localização da raiz do diretório de trabalho de um repositório non-bare. Se --git-dir ou GIT_DIR for especificado, mas nenhum entre --work-tree, GIT_WORK_TREE ou core.worktree for especificado, o diretório de trabalho atual será considerado como o nível principal da sua árvore de trabalho.

GIT_INDEX_FILE é o caminho apontado para o arquivo de index (somente repositórios non-bare).

GIT_OBJECT_DIRECTORY pode ser utilizado para especificar a localização do diretório que usualmente reside em .git/objects.

GIT_ALTERNATE_OBJECT_DIRECTORIES é uma lista separada por dois-pontos (formatada como /dir/one:/dir/two:…) a qual diz ao Git onde ele deve procurar por objetos caso não os encontre no GIT_OBJECT_DIRECTORY. Se você por acaso tiver muitos projetos com arquivos grandes que contenham exatamente os mesmos conteúdos, esta variável poderá ser usada para evitar o armazenamento de muitas cópias deles.

Pathspecs

Um “pathspec” refere-se à forma como você especifica caminhos para as coisas no Git, incluindo o uso de wildcards (caracteres curinga). Eles são utilizados no arquivo .gitignore, mas também na linha de comando (como em git add *.c).

GIT_GLOB_PATHSPECS e GIT_NOGLOB_PATHSPECS controlam o comportamento padrão dos curingas nos pathspecs. Se GIT_GLOB_PATHSPECS for definido como 1, os caracteres curinga agirão como curingas (o que é o padrão); se GIT_NOGLOB_PATHSPECS for definido como 1, os caracteres curinga apenas corresponderão a eles mesmos, o que significa que algo como *.c corresponderá apenas a um arquivo chamado “\*.c”, ao invés de qualquer arquivo cujo nome termine em .c. Você pode sobrescrever isso em casos individuais iniciando o pathspec com :(glob) ou :(literal), como em :(glob)\*.c.

GIT_LITERAL_PATHSPECS desabilita ambos os comportamentos acima; nenhum caractere curinga funcionará, e os prefixos de sobrescrita também serão desabilitados.

GIT_ICASE_PATHSPECS define todos os pathspecs para funcionarem de maneira insensível a maiúsculas e minúsculas (case-insensitive).

Criando Commits (Committing)

A criação final de um objeto commit no Git é normalmente feita por git-commit-tree, que utiliza essas variáveis de ambiente como sua fonte primária de informações, recorrendo aos valores de configuração somente se elas não estiverem presentes.

GIT_AUTHOR_NAME é o nome legível por humanos no campo “author” (autor).

GIT_AUTHOR_EMAIL é o e-mail para o campo “author”.

GIT_AUTHOR_DATE é a marcação de data/hora (timestamp) usada para o campo “author”.

GIT_COMMITTER_NAME define o nome legível para o campo “committer”.

GIT_COMMITTER_EMAIL é o endereço de e-mail para o campo “committer”.

GIT_COMMITTER_DATE é usado para a marcação de data/hora no campo “committer”.

EMAIL é o endereço de e-mail de alternativa (fallback) caso o valor da configuração user.email não esteja definido. Se isto não estiver definido, o Git recorre aos nomes de usuário do sistema e do host.

Operações de Rede

O Git usa a biblioteca curl para realizar operações de rede via HTTP, então GIT_CURL_VERBOSE diz ao Git para emitir todas as mensagens geradas por essa biblioteca. Isso é parecido com a execução de curl -v na linha de comando.

GIT_SSL_NO_VERIFY diz ao Git para não verificar os certificados SSL. Isto pode às vezes ser necessário se você estiver usando um certificado auto-assinado (self-signed) para hospedar repositórios Git via HTTPS, ou se você estiver no meio da configuração de um servidor Git mas ainda não instalou um certificado completo.

Se a taxa de dados de uma operação HTTP for menor do que GIT_HTTP_LOW_SPEED_LIMIT bytes por segundo por mais do que GIT_HTTP_LOW_SPEED_TIME segundos, o Git irá abortar aquela operação. Esses valores sobrescrevem os valores das configurações de http.lowSpeedLimit e http.lowSpeedTime.

GIT_HTTP_USER_AGENT define a string user-agent utilizada pelo Git ao se comunicar via HTTP. O padrão é um valor parecido com git/2.0.0.

Fazendo Diffs e Merges

GIT_DIFF_OPTS é um nome um pouco inadequado (misnomer). Os únicos valores válidos são -u<n> ou --unified=<n>, os quais controlam o número de linhas de contexto mostradas em um comando git diff.

GIT_EXTERNAL_DIFF é usado para sobrescrever o valor de configuração diff.external. Se ele for definido, o Git invocará este programa quando um git diff for invocado.

GIT_DIFF_PATH_COUNTER e GIT_DIFF_PATH_TOTAL são úteis por dentro do programa especificado por GIT_EXTERNAL_DIFF ou diff.external. O primeiro representa qual arquivo numa série está sofrendo o diff (começando por 1), e o último (latter) é o número total de arquivos no lote (batch).

GIT_MERGE_VERBOSITY controla a saída para a estratégia de merge do tipo recursive. Os valores aceitáveis são como a seguir:

  • 0 não tem saída alguma, com a possível exceção de uma única mensagem de erro.

  • 1 mostra somente os conflitos.

  • 2 também exibe alterações de arquivos.

  • 3 mostra quando arquivos foram pulados porque não haviam sofrido alterações.

  • 4 mostra todos os caminhos à medida que são processados.

  • 5 ou mais mostra informações detalhadas de depuração.

O valor padrão é 2.

Depuração (Debugging)

Quer realmente saber o que o Git está fazendo? O Git possui um conjunto bastante completo de logs de rastreio (traces) embutido, e a única coisa de que você precisa é ligá-lo. Os possíveis valores para essas variáveis são listados a seguir:

  • “true”, “1”, ou “2” – a categoria de rastro é escrita no stderr.

  • Um caminho absoluto começando com / – a saída do rastreamento será escrita naquele arquivo.

GIT_TRACE controla os rastros (traces) gerais, que não se encaixam em nenhuma categoria específica. Isto inclui a expansão de aliases, e também a delegação para outros subprogramas.

$ GIT_TRACE=true git lga
20:12:49.877982 git.c:554               trace: exec: 'git-lga'
20:12:49.878369 run-command.c:341       trace: run_command: 'git-lga'
20:12:49.879529 git.c:282               trace: alias expansion: lga => 'log' '--graph' '--pretty=oneline' '--abbrev-commit' '--decorate' '--all'
20:12:49.879885 git.c:349               trace: built-in: git 'log' '--graph' '--pretty=oneline' '--abbrev-commit' '--decorate' '--all'
20:12:49.899217 run-command.c:341       trace: run_command: 'less'
20:12:49.899675 run-command.c:192       trace: exec: 'less'

GIT_TRACE_PACK_ACCESS controla o rastreio das formas de acesso aos packfiles. O primeiro campo é o packfile sendo acessado, o segundo é o offset por dentro daquele arquivo:

$ GIT_TRACE_PACK_ACCESS=true git status
20:10:12.081397 sha1_file.c:2088        .git/objects/pack/pack-c3fa...291e.pack 12
20:10:12.081886 sha1_file.c:2088        .git/objects/pack/pack-c3fa...291e.pack 34662
20:10:12.082115 sha1_file.c:2088        .git/objects/pack/pack-c3fa...291e.pack 35175
# […]
20:10:12.087398 sha1_file.c:2088        .git/objects/pack/pack-e80e...e3d2.pack 56914983
20:10:12.087419 sha1_file.c:2088        .git/objects/pack/pack-e80e...e3d2.pack 14303666
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

GIT_TRACE_PACKET habilita rastreios a nível de pacotes (packet-level tracing) para operações de rede.

$ GIT_TRACE_PACKET=true git ls-remote origin
20:15:14.867043 pkt-line.c:46           packet:          git< # service=git-upload-pack
20:15:14.867071 pkt-line.c:46           packet:          git< 0000
20:15:14.867079 pkt-line.c:46           packet:          git< 97b8860c071898d9e162678ea1035a8ced2f8b1f HEAD\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done symref=HEAD:refs/heads/master agent=git/2.0.4
20:15:14.867088 pkt-line.c:46           packet:          git< 0f20ae29889d61f2e93ae00fd34f1cdb53285702 refs/heads/ab/add-interactive-show-diff-func-name
20:15:14.867094 pkt-line.c:46           packet:          git< 36dc827bc9d17f80ed4f326de21247a5d1341fbc refs/heads/ah/doc-gitk-config
# […]

GIT_TRACE_PERFORMANCE controla o registro de dados relacionados à performance. A saída exibirá quanto tempo em duração demorará a cada invocação específica feita para o git.

$ GIT_TRACE_PERFORMANCE=true git gc
20:18:19.499676 trace.c:414             performance: 0.374835000 s: git command: 'git' 'pack-refs' '--all' '--prune'
20:18:19.845585 trace.c:414             performance: 0.343020000 s: git command: 'git' 'reflog' 'expire' '--all'
Counting objects: 170994, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (43413/43413), done.
Writing objects: 100% (170994/170994), done.
Total 170994 (delta 126176), reused 170524 (delta 125706)
20:18:23.567927 trace.c:414             performance: 3.715349000 s: git command: 'git' 'pack-objects' '--keep-true-parents' '--honor-pack-keep' '--non-empty' '--all' '--reflog' '--unpack-unreachable=2.weeks.ago' '--local' '--delta-base-offset' '.git/objects/pack/.tmp-49190-pack'
20:18:23.584728 trace.c:414             performance: 0.000910000 s: git command: 'git' 'prune-packed'
20:18:23.605218 trace.c:414             performance: 0.017972000 s: git command: 'git' 'update-server-info'
20:18:23.606342 trace.c:414             performance: 3.756312000 s: git command: 'git' 'repack' '-d' '-l' '-A' '--unpack-unreachable=2.weeks.ago'
Checking connectivity: 170994, done.
20:18:25.225424 trace.c:414             performance: 1.616423000 s: git command: 'git' 'prune' '--expire' '2.weeks.ago'
20:18:25.232403 trace.c:414             performance: 0.001051000 s: git command: 'git' 'rerere' 'gc'
20:18:25.233159 trace.c:414             performance: 6.112217000 s: git command: 'git' 'gc'

GIT_TRACE_SETUP mostra as informações a respeito do que o Git está descobrindo em base no repositório e sobre o ambiente com que ele está interagindo.

$ GIT_TRACE_SETUP=true git status
20:19:47.086765 trace.c:315             setup: git_dir: .git
20:19:47.087184 trace.c:316             setup: worktree: /Users/ben/src/git
20:19:47.087191 trace.c:317             setup: cwd: /Users/ben/src/git
20:19:47.087194 trace.c:318             setup: prefix: (null)
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

Diversos

GIT_SSH, se for especificado, é o programa que será invocado no lugar de ssh quando o Git tentar se conectar em um host SSH. Ele é invocado de forma parecida a $GIT_SSH [username@]host [-p <port>] <command>. Note que isto não constitui a forma mais fácil para se customizar o jeito que o ssh é invocado; ele não suportará parâmetros extras de linha de comando. Para que possa suportar parâmetros extras na linha de comando, você pode usar o GIT_SSH_COMMAND, ou criar um script de wrapper (wrapper script) e definir GIT_SSH de modo que aponte a ele, ou usar o arquivo ~/.ssh/config.

GIT_SSH_COMMAND define o comando SSH que é utilizado quando o Git tentar se conectar a um host SSH. O comando é interpretado pelo próprio shell, e argumentos extras de linha de comando podem ser utilizados com ssh, tal como com GIT_SSH_COMMAND="ssh -i ~/.ssh/my_key" git clone git@example.com:my/repo.

GIT_ASKPASS substitui o valor de configuração core.askpass. Esse programa é invocado sempre que o Git precisa solicitar credenciais ao usuário; ele recebe um prompt de texto como argumento de linha de comando e deve retornar a resposta em stdout (consulte Armazenamento de Credenciais para saber mais sobre esse subsistema).

GIT_NAMESPACE controla o acesso a refs com namespace e equivale à flag --namespace. Isso é útil principalmente no lado do servidor, onde talvez você queira armazenar vários forks de um único repositório em um só repositório, mantendo apenas as refs separadas.

GIT_FLUSH pode ser usada para forçar o Git a usar E/S sem buffer ao escrever incrementalmente em stdout. O valor 1 faz o Git descarregar o buffer com mais frequência; o valor 0 faz com que toda a saída seja armazenada em buffer. O valor padrão (quando essa variável não está definida) seleciona um esquema de buffering adequado de acordo com a atividade e o modo de saída.

GIT_REFLOG_ACTION permite especificar o texto descritivo gravado no reflog. Eis um exemplo:

$ GIT_REFLOG_ACTION="my action" git commit --allow-empty -m 'My message'
[master 9e3d55a] My message
$ git reflog -1
9e3d55a HEAD@{0}: my action: My message