我越来越熟悉 git,并且正在学习如何将它用于我的 LaTeX 文档。但是,我根本不是 git 专家,因此我正在寻找进一步的建议。人们可以找到许多提示和技巧(在 TeX.SE 中也是如此),但我想重点讨论 TeX 文档上下文中的分支问题。
目前,我发现一个存储库一个文档的模型最适合我的需求。通过文档,我们可以考虑一篇文章。此外,我们假设存储库也正在推送到与协作者共享的远程位置。
我的问题是:我应该何时以及如何进行分支和合并?
我想到了一个工作流程应该是什么样子的想法,但我不确定它是否足够好,或者我是否遗漏了什么。 请参阅我的回答。
答案1
我犹豫着要不要这么说,但我认为你做错了;但我认为你已经接近所需要的了。
分支的目的是分离活动,不是结构部件。
因此,我不会为“简介”文件创建一个分支,而是为“开发简介”过程创建一个分支。例如,这个分支可能不仅包括 的更改,Introduction.tex
还包括Preamble.tex
(\usepackage{todonotes}
,可能)和Master.tex
(\input{Introduction}
,可能)。
话虽如此,我认为这只有在你作为团队的一员工作时才有用——例如,一个人做简介,一个人做第 1-3 章,一个人做第 4-8 章。
作为一名独立作者,我的工作方式如下(我使用git
):
- 大致来说,每个文档对应一个仓库
- 代表“公共”文档生命周期的主分支(也称为“发布”分支)
- 如果你确实需要它,那么你可以在发布之前积累其他分支的开发分支
- 特定分支主要的工作项目(例如“我正在从 Komascript 转到 Memoir”)
- 但我会在主分支或(如果需要的话)开发分支上进行正常的日常改进(例如,只是慢慢地添加段落)。
- 频繁提交小规模的变更(例如,将序言的提交分开可能会很有用
- 尽量遵守“不要提交损坏的版本”的准则(我尝试过,但并不总是成功)
- 广泛使用标记来记录图表中给定点的含义方法
当我创建发送给客户的文档时,我还做了一些奇怪的事情:
- 当文档准备好时提交所有内容(但不是直接的 PDF)
- 提交后,重新格式化文档并检查它(这会为我的 dogfooded 引入我的 git 提交引用
gitinfo
) - 将 PDF 输出重命名为 client.2013-03-19.pdf,并将其移动到名为“archive”的文件夹,该文件夹也位于 repo 中的某个位置
- 暂存并提交特定日期的 PDF,并标记相应提交。
我希望这个答案也能有所帮助:版本和 git 的自动分支
答案2
当我维护同一篇文档的两个版本时,我发现 git 分支模型很有用,比如说一个用于同行评审的单列版本和一个用于最终草稿的双列版本。但我遵循分支和变基策略而不是分支合并。
我发表文章的期刊要求作者提交一栏和两栏版本的稿件。稿件通常需要经过两到三轮审核才能被接受。
从一列变为两列通常意味着方程式中的换行符不同,有时图表和表格中的参数也不同。我通常从论文的单列版本开始。当我准备提交论文时,我会创建另一个分支two-column
并添加提交以更正方程式、图表和表格的格式。
在对论文进行修订时,我会检出master
(单列)分支,并进行相应的更改。然后,为了创建文档的双列版本,检出two-column
分支,然后根据 对其进行重新定基master
。
答案3
git
这里解释了我将如何与后端进行协作。
主要思想是人们会拥有大量文档,此外,复制整个树应该很容易。最后,如果 TeX 文档需要使用相同的 bib,那么所有文档都拥有相同的树对每个人都有好处。
这里有几个关键点:
- 每个文档都有自己的存储库(可以是远程放置在裸存储库中)
- 每份文件原则上都知道没有什么关于它是一个子模块。
- 这主要的repos 是一个容器,您可以在这里添加任何常规的东西,比如新文档的模板,模板徽标等。
- 子模块位于主模块内。每个子模块都是自给自足具有其自己的、独立的、历史记录等的存储库。
- 这主要的repos 不跟踪子模块中的任何内容,而是跟踪子模块的提交 ID。因此,这在某种程度上抽象了主 repos 中的版本,但在这里,主 repos 更像是一个容器而不是跟踪器。请记住,主 repos 跟踪子模块中的提交,并且不会随意更新子模块。因此,要检索每个文档中的最新版本,您应该执行以下操作:
- 进入子模块并执行拉取/更新
- 如果此更新应在主要的repo 你必须在主要部分提交它。
好的,我希望上面简要解释了子模块是什么以及它的作用。想想主要的repo 作为一个程序,并且每个文档作为程序中使用的库。通过跟踪库,可以顺利更新,并轻松回溯到可用的版本(如果适用)。
看到这个子模块链接以获得更一般的解释。
重点是,一旦你创建了一个主要的如果您有一个包含您团队所有文档的存储库,那么您可以告诉您的员工/同事获取那个,而不是获取这个、这个、这个等等。此外,如果您要与某人合作,但您不想与他分享所有内容,只需给他文档存储库,而不是主存储库。您仍然可以进行合作等。
好的,我创建了一个小型 bash 脚本供大家玩:
#!/bin/bash
# Script for creating a couple of examples of submodule
function crt_rep {
rm -rf $1 ; mkdir $1
pushd $1 ; git init
echo "Init" > test ; git add test ; git commit -a -m "Initial, created repo $1"
popd
}
crt_rep doc1
crt_rep doc2
# Ok, so now we have two repos...
# We create a last repo which is our parent repo
crt_rep all
# Save the current path (submodules needs full paths...)
tmp_path=$(pwd)
# Go into all and add the submodules
pushd all
# Add the submodules
git submodule add $tmp_path/doc1 doc1
git submodule add $tmp_path/doc2 doc2
# Do a status
git status
# The submodules are NOT fetched!
# This will do that (I have done it explicitly)
git submodule init doc1
git submodule update doc1
git submodule init doc2
git submodule update doc2
# Add the submodules to the repos
git commit -a -m "Added doc1 and doc2 to the repo"
# Get out
popd
# An example of tracking commits, not latest. we go into one submodule and do:
pushd doc1
echo "Second commit" > second
git add second
git commit -a -m "Added second commit"
popd
# Checkout the newest document
pushd all/doc1
git pull
popd
pushd all
git status # here, you will see that "main" has uncommitted edits (the doc1 is updated to a new commit)
popd
# Remove if the collaborator already existed
rm -rf collaborator
# We clone everything (notice here that the COMMITED version in all is the one that
# is pulled)
git clone --recursive $tmp_path/all collaborator
# Or if, git -v < 1.6.5
#git clone $tmp_path/all collaborator
#git submodule update --init
请仔细检查以了解其作用。
正如 Brent 所说,我认为您使用了太多的 rebase 语句。在我看来,它们主要用于分离多个分支(我认为在这种情况下这是非常过分的)。repo 中的所有编辑都应直接添加到主目录中,如果您希望它是临时的,只需将文件命名为临时文件(git 跟踪内容,而不是名称,因此历史搜索在这里应该没有问题)。
答案4
撰写论文或类似的作品时,需要其他人的意见在 pdf 上(而不是tex
),这是一个很好的策略,为每个审阅的版本和每个审阅者创建一个分支。
这使得以下工作流程成为可能:
- 分支到
reviewer-version
并以 pdf 格式分享当前状态给审阅者 - 签出你的
dev
或master
分支以继续工作 - 取回已审阅的文件
- 查看分支
reviewer-version
- 提交修复
- 合并到你的
dev
或master
分支
这使得你能够以可靠的方式应用来自不同审阅者的修复