git存储库中的备用/多个目录结构映射

时间:2011-04-10 18:54:43

标签: c git

我管理的是一个较大的(23,000 LOC包含/ src,5000个LOC用于样本),多平台,ANSI C代码库用于从8位嵌入式处理器和32KB闪存到桌面PC运行的所有内容视窗。此代码库将继续增长,我们将为其添加更多平台。

我目前正在使用Subversion维护它,但该公司正在转向使用所有版本控制的git。

我需要一种方法来对目录结构进行不同的映射,以便文件可以适应每个目标开发环境的现有结构。我希望能够从这些映射目录中检查更改,因为我们将在给定平台的目录结构中对库进行主动开发。例如,启动新平台可能会暴露库中的错误,并且最容易将其修复到位,并从该结构提交更改。

例如,一个平台可能具有以下结构:

  • SRC /富
  • 的src /富/平台
  • 的src / alternate_name_for_bar
  • 的src /巴兹
  • 包括/富
  • 包括/酒吧
  • 包括/巴兹
  • 样本/富
  • 样本/富/通用

虽然另一个可能是这样的:

  • LIB /布拉赫/富
  • LIB /布拉赫/富/平台
  • Lib / Blah / bar
  • Lib / Blah / foo / baz(注意baz作为foo的子目录而不是同级别)
  • include / foo
  • 包括/酒吧
  • include / baz
  • 样品/富
  • 样品/富/通用

存储库:

  • SRC /富
  • 的src /酒吧
  • 的src /巴兹
  • src / platform1(映射到平台1源上的foo / platform)
  • src / platform2(映射到平台2源上的foo / platform)
  • src / platform3(映射到平台3源上的foo / platform)
  • 包括/富
  • 包括/酒吧
  • 包括/巴兹
  • 样本/通用
  • samples / platform1(映射到平台1上的samples / foo)
  • samples / platform2(映射到平台2上的samples / foo)
  • samples / platform3(映射到平台3上的samples / foo)

我在存储库的目录结构中具有灵活性,但我想要一些有意义且易于维护的东西。我还希望将所有内容保存在单个存储库中,因为更改集可能会影响include中的一个头文件,src中的多个文件以及多个示例程序。

使用Subversion,我可以使用svn:externals来进行目录映射。存储库包含名为master的根目录中的所有文件,然后使用svn:externals将文件/目录从master映射到给定平台所需的任何布局的每个平台的其他根目录。

我对git很新,但我读过有关子模块的内容,它们似乎不符合要求,因为它们不允许目录映射,并且您无法提交跨多个子模块的更改(AFAIK)

大多数嵌入式开发都在Windows上进行,因此符号链接不适用于目录映射。

我有可能以错误的方式看待这个问题,并且我需要为每个平台提供一个存储库,从另一个存储库中提取公共代码。但是从我在git子模块上读到的内容来看,无法进行目录映射。

2 个答案:

答案 0 :(得分:2)

只要版本控制周期与存储库的其余部分足够独立,我就会建议共享模块(子树)的子模块。

另一个想法,恕我直言,将是主题分支。在主题分支中保留一些特定于平台的调整,以便您可以将它们“叠加”在正在开发的中心分支之上。

topgit是一个我非常喜欢管理主题分支更自动化的工具。根据我的经验,Topgit有一个相当陡峭的学习曲线,所以你可能想暂时回避它。

我当然会把所有东西放在一个回购中;如果你必须,你可以

  • 避免使用git子模块
  • 避免符号链接

并且仍然通过适量的脚本编写'逻辑'链接的子树:

请参阅git read-tree,例如

git read-tree --prefix=externals/ origin/3rdparty:i386/externals
git read-tree --prefix=samples/ origin/samples

请注意origin/3rdparty:i386/externals如何直接引用特定引用的子树,例如man git-rev-spec 中的详细信息)

只要您在.gitignore中保留externals/samples/包含此类动态链接子树的常规分支,您就不会遇到太多麻烦(将它们视为链接形式的readonly,就像svn externals一样。)

答案 1 :(得分:0)

所以我终于从Subversion转移到git,并根据@ peachykeen对我的问题的评论,我能够使用junction points进行目录映射。我刚刚创建了一个小批量文件,它通过成对的链接和目标进行循环,并使用rmdir删除旧链接,使用mklink /j创建新链接。

@echo off

:: Expand variables at execution time rather than at parse time.
setlocal EnableDelayedExpansion

SET MAPPING=    ^
    include\foo:include\foo ^
    include\bar:include\bar ^
    include\baz:include\baz ^
    src\foo:Lib\Blah\foo    ^
    src\bar:Lib\Blah\bar    ^
    src\baz:Lib\Blah\baz    ^
    src\util:Lib\Blah\foo\util  ^
    src\platform:Lib\Blah\foo\platform  ^
    samples\platform:Samples\foo    ^
    samples\common:Samples\foo\common   ^
    test:Test\foo

set PLATFORM=..\..\
set DRIVER=..\

for %%M in (%MAPPING%) do (
  for /f "tokens=1,2 delims=:" %%a in ("%%M") do (
    set SRC=%%a
    set DST=%%b
    if exist %PLATFORM%!DST! rmdir %PLATFORM%!DST!
    mklink /j %PLATFORM%!DST! %DRIVER%!SRC!
  )
)

这甚至可以作为git子模块与驱动程序一起使用。只需运行批处理文件一次即可设置联结。