-
1. Primeiros Passos
- 1.1 Sobre Controle de Versão
- 1.2 Uma Breve História do Git
- 1.3 O que é Git?
- 1.4 A Linha de Comando
- 1.5 Instalando o Git
- 1.6 Configuração inicial do Git
- 1.7 Obtendo Ajuda
- 1.8 Resumo
-
2. Fundamentos do Git
-
3. Ramificação (Branching) no Git
-
4. Git no Servidor
- 4.1 Os Protocolos
- 4.2 Colocando o Git em um Servidor
- 4.3 Gerando a sua Chave Pública SSH
- 4.4 Configurando o Servidor
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Opções de Hospedagem de Terceiros
- 4.10 Resumo
-
5. Git Distribuído
-
6. GitHub
-
7. Ferramentas do Git
- 7.1 Seleção de Revisão
- 7.2 Área de Stage Interativa
- 7.3 Fazendo Stash e Limpando
- 7.4 Assinando Seu Trabalho
- 7.5 Pesquisando (Searching)
- 7.6 Reescrevendo o Histórico
- 7.7 Reset Desmistificado
- 7.8 Merging Avançado
- 7.9 Rerere
- 7.10 Depurando com Git
- 7.11 Submódulos
- 7.12 Empacotando (Bundling)
- 7.13 Substituir (Replace)
- 7.14 Armazenamento de Credenciais
- 7.15 Resumo
-
8. Customizando o Git
- 8.1 Configuração do Git
- 8.2 Atributos do Git
- 8.3 Hooks do Git
- 8.4 Uma Política de Exemplo Imposta pelo Git
- 8.5 Resumo
-
9. Git e Outros Sistemas
- 9.1 Git como Cliente
- 9.2 Migrando para o Git
- 9.3 Resumo
-
10. Git Internals (Por Dentro do Git)
- 10.1 Encanamento e Porcelana (Plumbing and Porcelain)
- 10.2 Objetos do Git
- 10.3 Referências do Git
- 10.4 Arquivos de pacote (Packfiles)
- 10.5 Refspec
- 10.6 Protocolos de Transferência
- 10.7 Manutenção e Recuperação de Dados
- 10.8 Variáveis de Ambiente
- 10.9 Resumo
-
A1. Appendix A: O Git em Outros Ambientes
- A1.1 Interfaces Gráficas
- A1.2 Git no Visual Studio
- A1.3 Git no Visual Studio Code
- A1.4 Git no IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git no Sublime Text
- A1.6 Git no Bash
- A1.7 Git no Zsh
- A1.8 Git no PowerShell
- A1.9 Resumo
-
A2. Appendix B: Incorporando o Git nos seus Aplicativos
- A2.1 Linha de Comando do Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Appendix C: Comandos do Git
- A3.1 Configuração e Ajustes
- A3.2 Obtendo e Criando Projetos
- A3.3 Snapshots Básicos
- A3.4 Branches e Merges
- A3.5 Compartilhando e Atualizando Projetos
- A3.6 Inspeção e Comparação
- A3.7 Depuração
- A3.8 Patches
- A3.9 E-mail
- A3.10 Sistemas Externos
- A3.11 Administração
- A3.12 Comandos de Encanamento
A2.3 Appendix B: Incorporando o Git nos seus Aplicativos - JGit
JGit
Se você quiser usar o Git dentro de um programa Java, há uma biblioteca Git completa chamada JGit. O JGit é uma implementação relativamente completa do Git, escrita nativamente em Java e amplamente usada pela comunidade Java. O projeto JGit está sob o guarda-chuva do Eclipse, e sua página pode ser encontrada em https://projects.eclipse.org/projects/technology.jgit.
Configuração
Há várias maneiras de integrar o JGit ao seu projeto e começar a escrever código com ele.
Provavelmente, a mais simples é usar o Maven – a integração é feita adicionando o trecho a seguir à tag <dependencies> do seu arquivo pom.xml:
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>3.5.0.201409260305-r</version>
</dependency>
A version provavelmente já terá avançado quando você ler isto; consulte https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit para obter informações atualizadas sobre o repositório.
Depois dessa etapa, o Maven obterá e usará automaticamente as bibliotecas do JGit de que você precisa.
Se preferir gerenciar as dependências binárias por conta própria, há binários pré-compilados do JGit disponíveis em https://projects.eclipse.org/projects/technology.jgit/downloads. Você pode incorporá-los ao projeto executando um comando como este:
javac -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App.java
java -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App
Encanamento (Plumbing)
O JGit tem dois níveis básicos de API: encanamento (plumbing) e porcelana (porcelain). Essa terminologia vem do próprio Git, e o JGit se divide aproximadamente nos mesmos tipos de área: as APIs de porcelana (porcelain) são um front-end amigável para ações comuns no nível do usuário (o tipo de coisa para a qual um usuário comum utilizaria a ferramenta de linha de comando do Git), enquanto as APIs de encanamento (plumbing) permitem interagir diretamente com objetos de baixo nível do repositório.
O ponto de partida para a maioria das sessões com o JGit é a classe Repository, e a primeira coisa a fazer é criar uma instância dela.
Para um repositório baseado em sistema de arquivos (sim, o JGit permite outros modelos de armazenamento), isso é feito com FileRepositoryBuilder:
// Create a new repository
Repository newlyCreatedRepo = FileRepositoryBuilder.create(
new File("/tmp/new_repo/.git"));
newlyCreatedRepo.create();
// Open an existing repository
Repository existingRepo = new FileRepositoryBuilder()
.setGitDir(new File("my_repo/.git"))
.build();
O builder oferece uma API fluente para fornecer tudo de que precisa para encontrar um repositório Git, independentemente de o programa saber exatamente onde ele está.
Ele pode usar variáveis de ambiente (.readEnvironment()), partir de um local no diretório de trabalho e pesquisar (.setWorkTree(…).findGitDir()), ou simplesmente abrir um diretório .git conhecido, como acima.
Depois de obter uma instância de Repository, você pode fazer todo tipo de coisa com ela.
Aqui está uma pequena amostra:
// Get a reference
Ref master = repo.getRef("master");
// Get the object the reference points to
ObjectId masterTip = master.getObjectId();
// Rev-parse
ObjectId obj = repo.resolve("HEAD^{tree}");
// Load raw object contents
ObjectLoader loader = repo.open(masterTip);
loader.copyTo(System.out);
// Create a branch
RefUpdate createBranch1 = repo.updateRef("refs/heads/branch1");
createBranch1.setNewObjectId(masterTip);
createBranch1.update();
// Delete a branch
RefUpdate deleteBranch1 = repo.updateRef("refs/heads/branch1");
deleteBranch1.setForceUpdate(true);
deleteBranch1.delete();
// Config
Config cfg = repo.getConfig();
String name = cfg.getString("user", null, "name");
Há bastante coisa acontecendo aqui; vamos examinar uma seção de cada vez.
A primeira linha obtém um ponteiro para a referência master.
O JGit obtém automaticamente a referência master real, que reside em refs/heads/master, e retorna um objeto que permite consultar informações sobre a referência.
Você pode obter o nome (.getName()), bem como o objeto de destino de uma referência direta (.getObjectId()) ou a referência apontada por uma referência simbólica (.getTarget()).
Os objetos Ref também são usados para representar referências e objetos de tag, portanto você pode verificar se a tag está “peeled,”, o que significa que ela aponta para o destino final de uma sequência (possivelmente longa) de objetos de tag.
A segunda linha obtém o destino da referência master, que é retornado como uma instância de ObjectId.
ObjectId representa o hash SHA-1 de um objeto, que pode existir ou não no banco de dados de objetos do Git.
A terceira linha é semelhante, mas mostra como o JGit lida com a sintaxe rev-parse (para saber mais, consulte Referências de Branch); você pode passar qualquer especificador de objeto que o Git reconheça, e o JGit retornará um ObjectId válido para esse objeto ou null.
As duas linhas seguintes mostram como carregar o conteúdo bruto de um objeto.
Neste exemplo, chamamos ObjectLoader.copyTo() para transmitir o conteúdo do objeto diretamente para stdout, mas ObjectLoader também tem métodos para ler o tipo e o tamanho de um objeto, além de retorná-lo como um array de bytes.
Para objetos grandes (nos quais .isLarge() retorna true), você pode chamar .openStream() para obter um objeto semelhante a InputStream, capaz de ler os dados brutos do objeto sem carregá-los todos na memória de uma só vez.
As linhas seguintes mostram o que é necessário para criar um novo branch.
Criamos uma instância de RefUpdate, configuramos alguns parâmetros e chamamos .update() para efetuar a alteração.
Logo depois vem o código que exclui esse mesmo branch.
Observe que .setForceUpdate(true) é necessário para isso funcionar; caso contrário, a chamada .delete() retornará REJECTED e nada acontecerá.
O último exemplo mostra como obter o valor de user.name dos arquivos de configuração do Git.
Essa instância de Config usa o repositório que abrimos anteriormente para a configuração local, mas também detecta automaticamente os arquivos de configuração global e de sistema e lê seus valores.
Esta é apenas uma pequena amostra da API de encanamento completa; há muitos outros métodos e classes disponíveis.
Também não mostramos aqui como o JGit trata erros: por meio de exceções.
Às vezes, as APIs do JGit lançam exceções Java padrão (como IOException), mas também há vários tipos de exceção específicos do JGit (como NoRemoteRepositoryException, CorruptObjectException e NoMergeBaseException).
Porcelana (Porcelain)
As APIs de encanamento (plumbing) são bastante completas, mas pode ser trabalhoso combiná-las para alcançar objetivos comuns, como adicionar um arquivo ao index ou criar um novo commit.
Para facilitar essas tarefas, o JGit oferece um conjunto de APIs de nível mais alto, cujo ponto de entrada é a classe Git:
Repository repo;
// construct repo...
Git git = new Git(repo);
A classe Git oferece um bom conjunto de métodos de alto nível no estilo builder, que podem ser usados para construir comportamentos bastante complexos.
Vejamos um exemplo — fazer algo semelhante a git ls-remote:
CredentialsProvider cp = new UsernamePasswordCredentialsProvider("username", "p4ssw0rd");
Collection<Ref> remoteRefs = git.lsRemote()
.setCredentialsProvider(cp)
.setRemote("origin")
.setTags(true)
.setHeads(false)
.call();
for (Ref ref : remoteRefs) {
System.out.println(ref.getName() + " -> " + ref.getObjectId().name());
}
Esse é um padrão comum da classe Git; os métodos retornam um objeto de comando que permite encadear chamadas de método para definir parâmetros, e a execução ocorre quando você chama .call().
Neste caso, estamos solicitando ao remote origin as tags, mas não os heads.
Observe também o uso de um objeto CredentialsProvider para autenticação.
Muitos outros comandos estão disponíveis por meio da classe Git, incluindo, entre outros, add, blame, commit, clean, push, rebase, revert e reset.
Leituras Adicionais
Esta é apenas uma pequena amostra de tudo o que o JGit é capaz de fazer. Se tiver interesse e quiser saber mais, veja onde procurar informações e inspiração:
-
A documentação oficial da API do JGit pode ser encontrada em https://help.eclipse.org/latest/topic/org.eclipse.egit.doc/help/JGit/User_Guide/User-Guide.html. Ela está no formato Javadoc padrão, portanto sua IDE preferida para JVM também poderá instalá-la localmente.
-
O JGit Cookbook, em https://github.com/centic9/jgit-cookbook, contém muitos exemplos de como realizar tarefas específicas com o JGit.