处理这个问题的正确方法是使用像 Git 这样的版本控制系统。它旨在处理完全您所描述的内容。
cmets 中有几个关于使用 Git 完成您想要的任务的建议。但是,您似乎对库中文件的存储方式存在误解。
你在cmets中说:
我想从最新的存储库中构建任何版本的库(如果你愿意,可以从 Git 中新鲜提取),而无需从 Git 进行潜在的 100 次拉取
还有:
但是如果您了解分支,您就会知道通过切换会丢失之前的快照。因此,如果您从构建一个分支(获取 V1.0)开始,然后切换到第二个分支构建 V1.1,您将失去 V1.0。
查看这些 cmets 和您的示例文件结构,这表明您认为 V1.0 分支将包含 Lib1.c、Lib2.c、Lib3.c 和 Lib4.c,而 V1.1 分支将仅包含Lib3.c 并且 V1.2 分支将仅包含 Lib2.c 和 Lib3.c。这不是Git的工作方式。
以下是如何在 Git 中存储这些文件的示例:
首先将 V1.0 文件放入目录结构中:
[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:17 src
./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h
./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c
然后创建一个新的 git repo,添加文件并提交它们:
[dbush@db-centos7 mylib]$ git init
Initialized empty Git repository in /home/dbush/mylib/.git/
[dbush@db-centos7 mylib]$ git add *
[dbush@db-centos7 mylib]$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: inc/Lib1.h
# new file: inc/Lib2.h
# new file: inc/Lib3.h
# new file: inc/Lib4.h
# new file: src/Lib1.c
# new file: src/Lib2.c
# new file: src/Lib3.c
# new file: src/Lib4.c
#
[dbush@db-centos7 mylib]$ git commit
现在你已经提交了 1.0 版本的文件,接下来我们根据当前版本创建一个标签:
[dbush@db-centos7 mylib]$ git tag -a -m "version 1.0" V1.0
[dbush@db-centos7 mylib]$ git tag -l
V1.0
现在,Lib3.c 看起来像这样:
#include <stdio.h>
void lib3()
{
printf("lib3 1.0\n");
}
现在让我们对 1.1 版本进行更改:
#include <stdio.h>
void lib3()
{
printf("lib3 1.1\n");
}
我们可以看到工作副本和签入版本之间存在差异:
[dbush@db-centos7 mylib]$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: src/Lib3.c
#
no changes added to commit (use "git add" and/or "git commit -a")
[dbush@db-centos7 mylib]$ git diff
diff --git a/src/Lib3.c b/src/Lib3.c
index 3593018..12542d9 100644
--- a/src/Lib3.c
+++ b/src/Lib3.c
@@ -2,5 +2,5 @@
void lib3()
{
- printf("lib3 1.0\n");
+ printf("lib3 1.1\n");
}
然后我们提交更改:
[dbush@db-centos7 mylib]$ git add src/Lib3.c
[dbush@db-centos7 mylib]$ git commit -m "updated Lib3.c for version 1.1"
并将其标记为 1.1 版:
[dbush@db-centos7 mylib]$ git tag -a -m "version 1.1" V1.1
现在让我们假设我们想要构建 1.0 代码。我们签出标签:
[dbush@db-centos7 mylib]$ git checkout V1.0
Note: checking out 'V1.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at a1ee8c1... initial commit
[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:33 src
./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h
./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:33 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c
[dbush@db-centos7 mylib]$ cat src/Lib3.c
#include <stdio.h>
void lib3()
{
printf("lib3 1.0\n");
}
[dbush@db-centos7 mylib]$ cat src/Lib2.c
#include <stdio.h>
void lib2()
{
printf("lib2 1.0\n");
}
您可以看到完整的源代码树可用,并且 Lib3.c 是 1.0 版本,Lib2.c 也是如此。现在我们要构建 1.1,所以让我们获取 1.1 标签:
[dbush@db-centos7 mylib]$ git checkout V1.1
Previous HEAD position was a1ee8c1... initial commit
HEAD is now at 95a429c... updated Lib3.c for version 1.1
[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:35 src
./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h
./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:35 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c
[dbush@db-centos7 mylib]$ cat src/Lib3.c
#include <stdio.h>
void lib3()
{
printf("lib3 1.1\n");
}
[dbush@db-centos7 mylib]$ cat src/Lib2.c
#include <stdio.h>
void lib2()
{
printf("lib2 1.0\n");
}
您可以从这里看到,不仅存在 Lib3.c 的 1.1 副本,还存在所有其他文件及其 V1.0 内容。您无需进行多次签出,也不会丢失任何未在最新提交中更新的文件。
您可以按照上面的示例来设置您的 repo。所以你会:
- 将 1.0 文件放在所需的目录结构中
- 创建一个新的 git 存储库并提交文件
- 标签版本 1.0
- 复制 1.1 版的文件更改
- 提交更改的文件,然后标记版本 1.1
- 复制 1.2 版的文件更改
- 提交更改的文件,然后标记版本 1.2
- 等等……
如果您在转至新版本时需要删除文件,这也适用。例如,如果您在 1.3 版中删除了 Lib4.c,那么您将在签出标签 1.0、1.1 和 1.2 时看到该文件,但在签出标签 1.3 时不会看到。
因此,一旦您设置了 Git 存储库,您只需签出一个标签一次,您就拥有了所需的一切。
编辑:
当需要将这些文件用于多个(可能是并发的)构建时,Git 仍然非常适合。如果要保留建议的文件夹结构,则需要了解文件的完整历史记录以获取每个文件的正确版本,并且您仍然希望将每个相关源文件的副本复制到“活动”构建目录中这样一个构建创建的目标文件就不会被另一个构建覆盖。 Git 将为您完全管理所有这些。
Git 允许克隆本地存储库,并执行特定分支或标签的最小克隆,这样您只复制您需要的内容,而不是在进程中获取整个 git 历史记录,因此拥有多个副本是不是问题。你可以这样做:
[dbush@db-centos7 mylib]$ git status
# On branch master
nothing to commit, working directory clean
[dbush@db-centos7 mylib]$ cd ..
[dbush@db-centos7 ~]$ git clone --single-branch --branch V1.0 ./mylib mylib-v1.0
Cloning into 'mylib-v1.0'...
done.
Note: checking out 'a1ee8c1bfdbb20f3e0716212582338371b60d9bc'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
[dbush@db-centos7 ~]$ cd mylib-v1.0
[dbush@db-centos7 mylib-v1.0]$ git status
# Not currently on any branch.
nothing to commit, working directory clean
[dbush@db-centos7 mylib-v1.0]$ git branch -l
* (no branch)
[dbush@db-centos7 mylib-v1.0]$
--branch 选项表示克隆特定的分支或标签,而 --single-branch 选项创建一个仅包含给定标签的浅层克隆,因此克隆的 .git 目录不会很大并且可以创建很快。