Controle de alterações em LaTeX usando Git e SourceTree

Em meu site, indico aos meus alunos que sempre que possível e indicado, use o LaTeX. O LaTeX proporciona uma escrita mais estruturada, aliviando o autor de preocupações de formatação, referências cruzadas, referências bibliográficas, etc. Em especial para mim, que reviso as publicações dos alunos, quanto menos coisas pra me preocupar (será que o aluno incluiu todas as citações na referência?), melhor.

No entanto, o LaTeX possui duas grandes desvantagens: os editores não são WYSIWYG e não há um sistema de controle de alterações amigável como no Microsoft Word ou LibreOffice Writer.

A primeira questão, na minha opinião, não é um problema tão grande assim. Usuários novatos se beneficiam de interfaces WYSIWYG, mas usuários experientes, principalmente da área de informática, conseguem ter produtividade igual ou até superior usando interfaces somente texto (obviamente que isso se restringe a certos casos. Eu não trocaria meu editor de texto gráfico pelo vim!). Depois de um tempo, aliás, você se acostuma a olhar diretamente para a Matrix. (Por exemplo, estou escrevendo este post em HTML num editor de texto simples, sem WYSIWYG).

A segunda questão, no entanto, é pertinente. O controle de alterações faz falta. Saber exatamente o que a outra pessoa alterou no artigo e poder deixar notas que devem ser respondidas pelo colega é, de fato, bastante cômodo. Comecei, então, a buscar soluções para esta questão. Antes de me render a editores online como Authorea ou ShareLaTeX, queria tentar achar algo que não precisasse pagar (para ter mais de um artigo compartilhado) e que não fosse dependente de conexão Internet (fora a paranóia de colocar ideias de pesquisa não publicadas num servidor de terceiros — já chega DropBox e OneDrive!).

Perguntando ao oráculo, cheguei a uma pergunta no StackExchange: como fazer controle de alterações em LaTeX? Uma das respostas traz uma sugestão que, se pensarmos bem, é até bem óbvia:


Latex documents are plain text. Therefore you can handle tracking changes for Latex documents using the same robust methods that millions of software developers have been using for decades!

Ou seja: repositório de controle de versão (ex.: Git, SVN, etc.) + software de diferenciação (diff, ex.: FileMerge no Mac, Meld no Linux, WinMerge no Windows). O diff permite que você veja tudo que foi alterado da versão que você tem em relação à versão mais recente no repositório, com o bônus de poder navegar no histórico e retomar qualquer uma das versões mais antigas de um arquivo.

Comecei, então, a configurar um repositório Git no Nemo com a ideia de utilizar um aplicativo chamado SourceTree (viu? Em alguns casos sou bastante favorável a ferramentas gráficas!), que já vem com um diff embutido. Nas seções a seguir, explico como foi feita a configuração do repositório e como professor e aluno podem trabalhar com controle de alterações no LaTeX.

Configurando o Git no servidor

O próprio manual do Git traz uma seção sobre configuração do servidor, que segui praticamente à risca para criação de um repositório.

A única diferença foi o local do repositório. Ao invés de usar [cci]/opt/git[/cci], achei que valia mais a pena utilizar [cci]/home/git[/cci], pois seria mais fácil de lembrar de fazer o backup do [cci]/home[/cci] do que do [cci]/opt[/cci] quando necessário. No caso, criei o repositório [cci]/home/git/papers-vitorsouza.git[/cci], onde pretendo colocar todos as publicações (escritas com meus alunos ou não) que forem escritas em LaTeX.

Na prática (professor): siga as instruções do manual do Git, crie o usuário git e o repositório, não se esquecendo de bloquear o acesso shell ao servidor com [cci]git-shell[/cci].

Cadastrando um usuário no repositório

Para enviar (push) novas versões para o repositório ou obter (pull) modificações feitas por outros, o Git utiliza SSH para se conectar ao servidor. Dado que o repositório foi criado pelo usuário [cci]git[/cci], a princípio para acessar o repositório teria que se saber a senha desse usuário.

No entanto o SSH oferece uma alternativa utilizando chaves de criptografia. Mais uma vez, o manual do Git traz uma seção sobre geração de chave SSH que explica como proceder. No caso de usuários Windows, o PuTTY é o cliente SSH mais popular nesta plataforma e é usado como base pelo cliente que usaremos nesse tutorial (o SourceTree — veja no FAQ a pergunta How do I set up SSH keys for authentication?). Esta página indica como gerar chaves SSH para o PuTTY (pode ignorar a última instrução sobre o BitBucket se você não usa esse site).

Cada chave pública é composta de três partes, similar ao exemplo abaixo:

[cc]
ssh-rsa AAAAB3NzaC…51jeuYrSTn vitor.souza@ufes.br
[/cc]

O primeiro termo é o sistema criptográfico utilizado na chave. O segundo é a chave em si (no exemplo acima grande parte da chave foi suprimida, substituída por [cci]…[/cci]). O terceiro termo é um comentário sobre a chave e geralmente indica quem é o dono da chave ou de onde ela veio.

Na prática (professor): primeiro, o professor faz o procedimento para ele mesmo ter acesso (adicionando sua chave pública ao arquivo [cci]/home/git/.ssh/authorized_keys[/cci]).

Na prática (alunos): devem seguir esse procedimento e enviar ao professor a chave pública para que também sejam adicionadas. Lembrando que a chave privada não deve ser nunca compartilhada com ninguém!

Acessando o repositório

Criado o repositório e configurada a chave SSH, podemos acessar o repositório utilizando, preferencialmente, um cliente gráfico. A wiki do Git traz uma série de front-ends para o Git. Neste tutorial usaremos o SourceTree que, infelizmente, só está disponível para Mac e Windows. A sabedoria das massas indica o Giggle como um bom front-end Git para o Linux.

EDIT (17/11/2017): Mais recentemente, alguns alunos me sugeriram também o GitKraken.

No SourceTree, para acessar um repositório clique no botão + New Repository e escolha a opção Clone from URL. Preencha no campo Source URL o endereço SSH do repositório: [cci]git@dev.nemo.inf.ufes.br:~/papers-vitorsouza.git[/cci] e escolha um diretório local no seu computador no qual os arquivos serão copiados, conforme mostra a figura abaixo (clique para ampliar).

Obs. para meus alunos: o repositório para PGs e dissertações de mestrado é separado e tem como URL: [cci]git@dev.nemo.inf.ufes.br:~/greylit-vitorsouza.git[/cci]

EDIT (25/11/2017): Caso o aluno não queira obter o repositório inteiro, pode obter apenas o seu diretório (solicitando que o professor crie o diretório e faça commit/push pro repositório) utilizando uma funcionalidade do Git chamada de sparse checkout, conforme descrito nesta resposta do StackOverflow.

Se tudo estiver certo com seu acesso SSH ao repositório (configurado anteriormente) o SourceTree irá obter todos os arquivos do servidor e copiá-los para o diretório que você escolheu no seu computador, por fim adicionando o novo repositório à lista exibida em sua tela inicial. Um duplo-clique no nome do repositório abre a janela exibida na figura abaixo. Como você acaba de obter os arquivos do servidor e não fez nenhuma alteração neles, não há nada para fazer commit.

Nessa tela você pode ver toda a estrutura do repositório alterando o filtro atual na parte superior da tela da opção padrão Pending files, sorted by path para All files, sorted by path. À direita do campo de filtro, um botão permite alterar a visão para Tree view para ver os arquivos em uma árvore de diretórios. O resultado é mostrado na figura abaixo.

No exemplo acima há um artigo no repositório. A estrutura de diretórios representa alunos e seus artigos. A partir da raiz, a pasta [cci]bfmartins[/cci] representa uma aluna de mestrado. Dentro de sua pasta encontram-se os artigos em que ela for a primeira autora. Nesse momento, ela estava trabalhando em um artigo sobre FrameWeb 2.0, para a conferência WISE 2015, daí a pasta [cci]2015-wise-frameweb2[/cci] (ano – sigla conferência – assunto do artigo).

Selecionando um arquivo mostra seu conteúdo atual. Clicando com o botão direito em um arquivo é possível abri-lo (no editor padrão configurado no sistema operacional) escolhendo a opção Open.

Enviando modificações para o repositório

Tendo o repositório atualizado em seu computador, você pode trabalhar nos arquivos localmente para depois enviar as alterações para o servidor. Além disso, como estamos usando o Git, é criado um repositório local no seu computador, de modo que você pode fazer commits de suas alterações mesmo estando offline. Depois basta enviar (push) os commits para o servidor.

É importante entender que são dois passos separados! Eles podem ser feitos de uma vez só, mas muitas vezes o aluno se confunde, faz o commit local, não envia (push) para o repositório e o professor não consegue revisar as alterações!

Ao alterar algum arquivo do repositório, ele muda o ícone do arquivo na árvore de diretórios do SourceTree, como mostra a figura abaixo. Clicando no arquivo, o SourceTree mostra a diferença (diff) entre o arquivo anterior e o atual (considerando seu repositório local).

A ferramenta de diff do SourceTree não possui suporte a quebra de linhas. Se você quiser ver exatamente o que mudou na linha de forma mais fácil, pode usar alguma ferramenta externa. No Mac o SourceTree vem configurado pra usar o FileMerge. Clicando com o botão direito no arquivo e selecionando External diff, ele abre as duas versões do arquivo no FileMerge, como mostra a figura abaixo.

Após ter trabalhado num trecho do artigo, pode-se fazer o commit, em dois passos. Primeiro, é preciso indicar o que vai entrar no commit. Isso é feito clicando na caixa de marcação que fica à esquerda dos arquivos. Se quiser selecionar todos os arquivos, basta clicar na caixa de marcação à esquerda do título Unstaged files. Os arquivos selecionados passam para a listagem superior, chamada Staged files.

O segundo passo consiste em clicar no botão Commit na barra de ferramentas do topo da janela, inserir (em inglês) uma descrição breve do que você fez desde o último commit e enviar suas alterações para seu repositório local. Caso queira enviá-las diretamente ao repositório remoto, marque a opção Push changes immediately to origin/master antes de enviar. A figura abaixo mostra o SourceTree momentos antes do commit ser efetuado.

Se você fez apenas commits locais, sem enviar ao servidor, o número de commits pendentes será exibido acima do botão Push da barra de ferramentas no topo da janela. Basta clicar nele para enviar as modificações para o servidor. Quando mais de um autor trabalha no mesmo artigo, é importante enviar as alterações para o servidor com frequência (ao menos no final do dia ou cada vez que você fizer uma pausa na sua tarefa de escrita, por exemplo para o almoço). Isso evita que dois ou mais autores modifiquem o mesmo artigo e causem conflito ao tentarem enviá-lo ao servidor. É possível resolver eventuais conflitos, mas deixarei esse assunto para outro momento.

Obtendo alterações do repositório

O SourceTree verifica de tempos em tempos o repositório remoto (você pode forçar a verificação clicando no menu Repository, item Refresh Remote Status). Quando algum colega efetua alterações nos arquivos e os envia ao servidor, notificações aparecerão tanto na tela inicial quanto na área de trabalho do repositório específico. A figura abaixo mostra um exemplo para o repositório konangelop-papers que eu compartilho com um colega da Universidade de Trento.

Como pode ser visto na figura, a tela inicial mostra dois números ao lado de master (que é o nome do ramo, ou branch, que estamos trabalhando): 8 arquivos sofreram modificações ao longo de 20 commits. Na área de trabalho do repositório o número de commits aguardando no servidor também são mostrados acima do botão Pull na barra de ferramentas no topo da janela. E, intuitivamente, é clicando neste botão que você traz os commits do servidor para seu repositório local, atualizando assim seus arquivos.

Enfim, controle de alterações no LaTeX (atualizado em 25/02/2016)

Com a infraestrutura pronta e as ferramentas adequadas, enfim podemos chegar a um processo de controle de alterações em documentos LaTeX (por mais primitivo que ele possa parecer para usuários de Word/Writer). O controle do que foi alterado pelo colega é feito usando o diff, conforme já exemplificado acima. Falta, então, uma maneira de deixar notas e respondê-las.

Seguindo a mesma lógica do início desse post, seria interessante instalar no servidor do Nemo uma ferramenta que permitisse revisão de código como oferecida pelo GitHub. Eventualmente eu experimentarei instalar e usar o Gerrit, mas por enquanto estou usando uma solução mais simples.

A solução envolve um pacote LaTeX chamado colorinlistoftodos, que permite adicionar texto em caixas coloridas, semelhantes às usadas nos comentários de Word/Writer (porém ficam no corpo do texto e não numa coluna lateral). Para usá-lo, é preciso incluir algumas definições no início do arquivo:

[cc_latex]
% Colorinlistoftodos package: to insert colored comments so authors can collaborate on the content.
\usepackage[colorinlistoftodos, textwidth=20mm, textsize=footnotesize]{todonotes}
\newcommand{\aluno}[1]{\todo[author=\textbf{Aluno},color=green!30,caption={},inline]{#1}}
\newcommand{\vitor}[1]{\todo[author=\textbf{Vítor},color=red!30,caption={},inline]{#1}}
[/cc_latex]

Feitas as definições, eu incluo notas ao longo do documento usando a macro [cci_latex]\vitor{}[/cci_latex] e o aluno responde com [cci_latex]\aluno{}[/cci_latex] (trocar [cci_latex]aluno[/cci_latex] e [cci_latex]Aluno[/cci_latex] pelo nome do aluno). Na configuração acima, o aluno comenta usando caixas verdes e eu respondo com caixas vermelhas. A figura abaixo mostra uma simulação de uma discussão sobre o primeiro parágrafo de um artigo de exemplo.

No exemplo, eu questiono uma afirmação do aluno (ou porque eu não tenho certeza ou porque acho que deve ser modificado, mas quero que o aluno reflita sobre a questão). Após efetuar o pull da nova versão do repositório e ver o comentário, o aluno responde, justificando seu texto original. Caso o aluno tivesse concordado com a mudança da frase, faria a modificação do texto e adicionaria um comentário diferente abaixo do comentário do professor: [cci_latex]\aluno{OK. Alterado.}[/cci_latex].

Isso ilustra a importância de sempre continuar a discussão até o fim. Apenas quando não houver mais nada a responder que o professor irá excluir todos os comentários, encerrando a questão. De qualquer forma, o aparecimento e desaparecimento de comentários nas versões do artigo ficarão visíveis no diff.

Outra coisa importante é usar um bom editor LaTeX que permita navegação entre código fonte e PDF. O TeXstudio, mostrado na figura acima, tem esta funcionalidade. Se o usuário segurar a tecla Command (no Mac) ou Ctrl (Windows/Linux) e clicar em um parágrafo do código-fonte, o mesmo é exibido no PDF à direita e vice-versa (Command+click ou Ctrl+click no PDF à direita leva ao trecho no código-fonte).

Em resumo: passo a passo da escrita colaborativa em LaTeX

1 – Para o primeiro acesso, o professor registra o aluno nas chaves autorizadas do repositório;

2 – Se for primeiro acesso, o aluno clona o repositório em sua máquina local usando o SourceTree;

3 – O aluno obtém o template LaTeX da conferência e monta o esqueleto do artigo, colocando-o na pasta apropriada dentro do repositório: [cci_bash]${username}/${ano}-${sigla}-${assunto}/submitted[/cci_bash], onde:

  • [cci_bash]${username}[/cci_bash] é definido pelo professor (em geral primeiro nome + último sobrenome);
  • [cci_bash]${ano}[/cci_bash] é o ano previsto para publicação do artigo. No caso de conferências, é o ano da mesma;
  • [cci_bash]${sigla}[/cci_bash] é a sigla da conferência, periódico, livro, etc. (ou seja, local de publicação);
  • [cci_bash]${assunto}[/cci_bash] é um resumo em poucas palavras (preferencialmente uma) do que trata o artigo;
  • [cci_bash]submitted[/cci_bash] é o diretório que contém a versão enviada para revisão.

No caso de artigos de conferência aprovados, é solicitada uma versão camera ready do artigo. Quando isso acontecer, o aluno pode cria uma cópia da pasta [cci_bash]submitted[/cci_bash] com o nome [cci_bash]x-camera-ready[/cci_bash]. No caso de artigos de periódicos que possuem múltiplas revisões, podem ser criadas cópias com nomes [cci_bash]x-review-01[/cci_bash], [cci_bash]x-review-02[/cci_bash], etc.;

4 – Assim que tiver escrito o suficiente para sofrer revisão, o aluno assegura-se de que não há erros ortográficos no documento (use um revisor ortográfico!) e de ter enviado todos os commits para o servidor. Então, solicita ao professor que faça a revisão do documento (ou de partes do mesmo);

5 – O professor fará o pull do documento e sua revisão, corrigindo diretamente o que achar apropriado e adicionado comentários com [cci_latex]\vitor{}[/cci_latex] (fundo vermelho) quando tiver dúvidas ou quiser dar explicações. Ao final da revisão, alertará o aluno para atualizar seu repositório local;

6 – Ao obter uma versão revisada do repositório, o aluno deve:

  1. Fazer o diff entre sua versão anterior e a nova versão revisada pelo professor para ver o que foi alterado. No caso do professor ter feito alguma alteração que o aluno não concorda, ele deve adicionar uma nota ([cci_latex]\aluno{}[/cci_latex], fundo verde) questionando a alteração;
  2. Responder todos os comentários do professor antes de enviar uma nova versão para revisão, seja efetuando as alterações pedidas (e comentando “OK”), seja respondendo com um questionamento, discordando, argumentando, etc.
  3. Passar novamente o corretor ortográfico caso tenha escrito novos parágrafos.

7 – Produzindo uma nova versão e enviando-a ao repositório no servidor, o aluno avisa ao professor e o ciclo continua até a versão final do artigo.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

code