我已经在使用PVCS控制版本,但是我将要开始一个新项目,并希望迁移到Git / SVN并保持与以前相同的结构。
代码是C,它的结构使得每个C“对象”都有其自己的标记,其中仅包含C文件和必要的H文件。
在Git / SVN中是否可以从主干创建一个分支,该分支仅包含该“对象”进行编译,制作标签并将更改合并到主干中所需的文件?
我尝试过Git,但是每次创建分支时,我都有所有文件,包括不需要的其他“对象”中的C和H文件。
我不知道是否还有另一个VCS可以创建这种部分标签。
答案 0 :(得分:1)
PVCS似乎是面向文件的(如CVS或RCS),具有集中存储(如CVS)和锁定(也如CVS)。
SVN是面向提交(和集中式)的,但是将分支视为文件子树,具有合并模型而不是锁定模型(尽管SVN实际上也提供文件锁定)。在某些情况下,该 可能与您使用标签的方式兼容。但这可能不是:如果您在单个文件系统中位于同一文件系统位置,而对各个文件进行了不同的标记,例如dir/sub/file1.c
具有标签A和B,而dir/sub/file2.c
具有完全不同的标签D和E,则不会也可以一起玩。
Git和其他现代VCS是分布式的,而不是集中的和面向提交的。分发系统时,锁定文件的整个概念几乎是敬酒的:没有中央机构声明谁拥有锁定。因此,这些都使用合并模型。 Git还没有
(将其与 reachability 的思想结合在一起,为Git提供了丢弃不需要的对象的能力:与某些其他现代的图形化版本控制系统不同,提交比其他任何内部对象都没有特殊之处。坦率地说,这可能会让人迷失方向:在其他面向提交的VCS中,一旦提交了一个提交,它就会永久地附加到单个分支上,并且您始终可以在该分支中找到它。因此,Git在这里甚至是一个飞跃比例如Mercurial。)
每当您拥有一个面向文件的版本控制系统时,很容易挑选出特定的文件,因为这就是VCS在下面工作的方式。进入提交模型后,“工作区”(在该特定的VCS中被调用的任何内容,Git都使用短语 work-tree 或 working directory 或类似的名称)这些行)必须与特定的提交匹配,因为您没有获得fileX.c
的V版本,而是得到 all 组成V版本的文件。从理论上讲,可以将其与 sparse checkout 和多个工作区结合使用,以便工作区1的V1版本为稀疏提取的file1.c
,工作区2的V2版本为稀疏提取的{{ 1}},依此类推;但是您将一直与模型争斗。这可能不是一个好主意。
最后,我认为除非您坚持使用面向文件的VCS,否则您将不得不更改工作流程。
答案 1 :(得分:0)
尽管您对Git分支的理解有些困惑,但我想这可能是可行的。
首先,关于分支:在Git中,它们只是对最后一次提交的引用(在内部,分支是其中仅包含提交哈希的文件)。
Git,PVCS和SVN的工作方式都非常不同。
在Git中,如果要每个分支分隔文件,则可以(尽管 异常)。创建基础分支的建议如下:
创建您的git存储库:
ghislain@linux (1): /tmp/example (master) ✔
> git init .
Initialized empty Git repository in /tmp/example/.git/
创建文件(尽管您可能已经拥有了它们):
ghislain@linux (1): /tmp/example (master #) ✔
> touch foo.c foo.h bar.c bar.h
进行一次初始提交(它将作为您所有分支的基础):
ghislain@linux (1): /tmp/example (master #) ✔
> touch README.md
ghislain@linux (1): /tmp/example (master #) ✔
> git add README.md && git commit -m 'Initial commit'
[master (root-commit) a9a05f3] Initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
使用相关文件为每种文件类型创建一个分支:
ghislain@linux (1): /tmp/example (master) ✔
> git checkout -b files-foo master
Switched to a new branch 'files-foo'
ghislain@linux (1): /tmp/example (files-foo) ✔
> git add foo.*
ghislain@linux (1): /tmp/example (files-foo +) ✔
> git commit -m 'foo added'
[files-foo 558cdc6] foo added
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 foo.c
create mode 100644 foo.h
做一些修改,更新,处理所述文件:
ghislain@linux (1): /tmp/example (files-foo) ✔
> vim foo.h
ghislain@linux (1): /tmp/example (files-foo *) ✔
> git add foo.h
ghislain@linux (1): /tmp/example (files-foo +) ✔
> git commit -m 'foo.h updated'
[files-foo 9565594] foo.h updated
1 file changed, 1 insertion(+)
对其他文件执行相同操作:
ghislain@linux (1): /tmp/example (master) ✔
> git checkout -b files-bar master
Switched to a new branch 'files-bar'
ghislain@linux (1): /tmp/example (files-bar) ✔
> git add bar.*
ghislain@linux (1): /tmp/example (files-bar +) ✔
> git commit -m 'bar files added'
[files-bar 9f78382] bar files added
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar.c
create mode 100644 bar.h
您的提交日志最终将如下所示,每个文件“类型”一个分支:
ghislain@linux (1): /tmp/example (files-bar) ✔
> git log --graph --oneline --all
* 9f78382 (HEAD -> files-bar) bar files added
| * 9565594 (files-foo) foo.h updated
| * 558cdc6 foo added
|/
* a9a05f3 (master) Initial commit
如果要处理一组文件,则需要git checkout <related-branch>
并在那里提交。
但是,如果您需要一些交叉引用或通用,可能会变得棘手
工作。对于后者,您必须提交master
并重新分配分支
最重要的是(如果您想保持日志清洁)。
总而言之,它可以工作,但最终可能变得非常麻烦 管理。我不知道您的项目如何运作,但可能更简单 在一起,并使用可能更经典的分支工作流程,尤其是如果您 是Git的新手。
答案 2 :(得分:0)
我无法谈论Subversion如何处理此问题的细节;真的git和subversion是完全独立的问题。我通常可以说我不相信Subversion分支是这样工作的。
我可以肯定地说,这不是git分支的工作方式。在其他答案中,您可以一起破解某些东西以近似该行为,但我建议您反对。迟早会引起麻烦。
如果要分别跟踪和编译文件集,则应将它们保存在单独的存储库中,并可能与将其视为子模块的“父存储库”一起使用。
更一般地说,“切换工具,但保持当前工具的结构”的目标不是很现实。每个源代码控制工具都有其自己的项目模型及其内容和历史记录。如果您喜欢现有的结构,则可能希望继续使用现有的工具。如果您使用的工具运行不正常,则可能是该工具使用的结构的症状。