使用 ClearCase 和 Git 实现理想的工作流程
Toward an ideal workflow with ClearCase and Git
简介
这不仅仅是事实,对于少数人维护的大型项目,使用 ClearCase(而非 UCM)作为主要 SCM 是一个非常低效的解决方案。当它是企业标准时,我们坚持使用它,我们需要找到一个有效的解决方法。
ClearCase 的常用工作流由一个 master
分支、一个 develop
分支和几个新功能分支组成。
o--------o (feature)
/ \
----o--o---o-----o----o (develop)
/ \ \
*----------o---------o (main)
例子
其实我所说的特性也可以是简单的重构,比如项目内部的大量重命名。在这个例子中,因为 ClearCase 是以文件为中心的,所以我们总是需要一个临时分支(在非 UCM CC 中没有原子签入)。创建一个新分支是痛苦的,拥有正确的配置规范是一项艰巨的任务。从这里,我看到了两个解决方案:
成为公司并开始对所有文件进行大量检查。因为 SCM 环境与 ClearCase 服务器不在同一个站点上,所以一切都变慢了。我计算每个文件 2 秒,1k 文件计算 8 分钟。第一次喝咖啡休息后,我们开始工作并签入所有文件(又浪费了 8 分钟)。一些测试、新的大规模签出、错误修复、大量签入、合并到 develop
分支,最终我们删除了不再有用的 feature
分支。
在这个解决方案中,一切都很慢,消耗了大量的咖啡因,而且工作流程效率很低。我认为这不是一个好的解决方案。
因为我们想跟踪我们的更改,我们不想浪费时间 checkin/out 所有项目的文件,我们从 Git 初始化一个存储库快照视图。实际上,Git 存储库可以位于 ClearCase 之外的任何其他地方。这些更改是在 Git 的帮助下在本地进行的,一旦一切都完成,该项目就会通过 clearfsimport
推回到 ClearCase 上。在此之后,我们还需要合并 feature
分支。这是在 CC 中完成的。然后可以删除功能分支。
此解决方案需要大量操作。此外,如果我们拼错目标视图或忘记删除所有临时文件,clearfsimport
可能会非常危险。最后但同样重要的是,最终合并必须在 CC 上完成。
快照视图
在我的示例中,我没有提到快照视图,因为它们与 Git 不兼容。根据时间戳识别的被劫持文件。如果我手动修改文件并恢复其原始修改日期,ClearCase 将看不到任何更改。这可能非常危险,下面的示例证明了这一点。
如果你不相信我,你可以试试这个:
stat -c 'touch --no-create -d "%y" "%n"' foo > restore_timestamp
echo "ClearCase will not see this" >> foo
source restore_timestamp
rm restore_timestamp
使用此机制,没有 Git 存储库可以驻留在 ClearCase 快照视图中。
分离 Git 存储库
我怀疑我们能否找到解决临时分支创建要求的方法。合并必须在 ClearCase 上完成,即使 Git 保留了所有内容。
我尝试广泛使用 Copy/Paste 来将完全独立的 Git 存储库与 ClearCase 同步。在最终合并之前,我 copy/paste 在新的 Git 分支中 develop
分支的当前状态,并尽快进行合并。最后,我使用 clearfsimport
将修改推回 develop
分支。
如果有人想在合并过程中访问该项目,此操作可能非常危险。为此,开发分支在运行过程中不得不被锁定或保留。不幸的是,这个额外的操作在 ClearCase 上非常耗时。
ClearCase“git checkout -b 功能”等效
在 Git 中,当我想创建一个新分支时,我只需键入:
git checkout -b feature
就是这样,我可以马上处理我的新功能。在 ClearCase 上,情况有些不同。
首先,我需要在要创建分支的位置放置一个标签。从 Windows 使用 Cygwin,我可以这样做:
LABEL=my_temporary_label
VOB=vob_name
cleartool mklbtype -global -nc lbtype:${LABEL}@\${VOB}
cleartool mklabel -replace ${LABEL} `cleartool find . -cview -print -nxn | awk '{printf "%s ", [=14=]}'`
cleartool find . -cview -type l -exec 'cleartool ls %CLEARCASE_XPN%' | \
perl -p -e 's/\/\//g' | \
perl -p -e 's/\r//g' | \
perl -e 'while(<>) {s@([.]/)(.*/)(.*-->\s*)@@;print;}' | \
xargs -n1 cleartool mklabel ${LABEL}
但是,我们需要小心,因为符号链接没有展开。
然后,必须创建一个分支:
mkbrtype –c "Temporary Branch" my_temporary_branch
要在此分支上工作,需要创建一个视图:
cleartool mkview -tag my_temporary_view \shared\path\to\viewStorage\my_temporary_view.vws
必须编辑配置规范:
element * CHECKEDOUT
element .../lost+found -none
element * .../develop_branch/LATEST
mkbranch develop_branch
element * /main/A_LABEL_WHERE_THE_BRANCH_IS_BRANCHED_ON
element * /main/LATEST
end mkbranch develop_branch
至此,分支创建完成。我们可以处理我们的功能。简单吧?
在Git,我一般一天创建3-5个分支。我不认为我可以用 ClearCase 做同样的事情。我错了吗?
讨论
所提出的两个解决方案都不太好,因为它们都需要在 ClearCase 上进行大量耗时的操作(创建分支、设置视图、签入、签出、合并、删除分支)。
我正在寻找一种不涉及复杂操作的解决方案。我仍然相信 Git 可能是一个很好的盟友,但 ClearCase 和 Git 如何协同工作?
我想我们可以使用一些脚本。我最近发现 git-cc 这可能是一个好的开始。不幸的是,这个项目还不成熟。
我还没有研究过这种方法,但我认为有一个解决方案,我们可以在 Git 中使用 ClearCase 快照视图。在进行任何更改之前必须保存每个文件的时间戳:
find . -type f -exec stat -c 'touch--no-create -d "%y" "%n"' {} \; > restore
从那里,我们可以在 Git 上工作,一旦到了将更改推送到 ClearCase 或只是从开发分支中提取更改的时间,就可以在所有文件上恢复原始时间戳,但自上次同步以来修改的文件:
source ./restore
git diff --name-only SHA1 SHA2 | xargs touch
问题
在 Whosebug 上,人们喜欢精确的问题,而不是基于主要观点的问题。因此,在这个相当长的介绍之后,我终于可以问我的问题了:
我已经尝试了很多不同的方法来改进我使用 ClearCase 的工作流程,但是使用 以文件为中心 SCM 的大型项目不是直截了当。我相信 Git 会有很大帮助,但我需要找到一个允许本地 git
存储库与 ClearCase 同步的工作流,并且如果可能的话,不需要临时分支。
可以吗?
Actually, what I call a feature could be also a simple refactoring, such as a massive renaming inside the project. In this example, and because ClearCase is file-centric, we always need a temporary branch (no atomic checkin in non-UCM CC).
Creating a new branch is painful and having the right config-spec is a struggling task
所以...不创建临时分支?
如果要与 Git 协作使用,仅在 Git 存储库中创建该功能分支,在 Git 存储库中进行最终合并,然后 clearfsimport 主 ClearCase 视图中的结果。
来自VonC
的可能解决方案
在 VonC 的 中,他建议不要使用中间分支并使用 Git 管理所有内容。
我想通过一个例子来展示他的方法。我们从 ClearCase 上的这个配置开始:
o------o----o (develop)
/ \
*----------o (main)
想法是使用 Git 来促进新功能的开发,最终将合并到 develop
分支。
我们首先将 ClearCase 项目复制到本地文件夹并初始化一个 Git 存储库(如果 Git 存储库不存在)。
WORKSPACE=~/foo
cp `cleartool ls -r | grep '@@' | sed 's/@@.*$//'` $WORKSPACE
cd $WORKSPACE
git init
git add .
git commit -m "Initial commit"
git checkout -b feature
我们花了一些时间在自己的本地 Git 分支上开发该功能:
x----x--x---x----x (feature on Git)
/
x---------- (master on Git)
/
o------o----o------o----o (develop)
/ \
*----------o (main)
一天结束时,是时候从 ClearCase 同步可能的更改了:
git checkout master
git --ls-files | xargs rm
cd $CCVIEW
cleartool ls -r | grep '@@' | sed 's/@@.*$//' > $WORKSPACE/ccview
cd $WORKSPACE
cat ccview | xargs -n1 cp {} $WORKSPACE
cat ccview | xargs git add
git commit -m "Imported from CC"
现在我们已经在 feature
分支上进行了多次提交,并且 master
Git 分支与 ClearCase 同步。
x----x--x---x----x (feature on Git)
/
x-----------o (master on Git)
/ /
o------o----o------o----o (develop)
/ \
*----------o (main)
我们一定不要忘记在整个合并过程中锁定ClearCase View。这是为了防止其他开发人员看到他们自己的更改被 clearfsimport
删除。要锁定 ClearCase 分支很容易:
cleartool lock brtype:$BR_NAME
然后可以在 Git:
上完成合并
git checkout master
git merge feature
feature
Git 分支与 master
合并。
x----x--x---x----x (feature on Git)
/ \
x-----------o--------o (master on Git)
/ /
o------o----o------o----o (develop)
/ \
*----------o (main)
可以将修改推回 ClearCase
OUT="$(mktemp -d)"
cp -v --parents `git ls-files | sed 's/[^ ]*\.gitignore//g'` $OUT
clearfsimport -comment 'clearfsimport' -rec -unco -nset $OUT $CVIEW
rm -rf $OUT
并且可以解除锁以重新授权分支上的更改
cleartool unlock brtype:$BR_NAME
。
x----x--x---x----x (feature on Git)
/ \
x-----------o--------o (master on Git)
/ / \
o------o----o------o----o------------o (develop)
/ \
*----------o (main)
除非我们需要继续,否则 Git 存储库和本地工作区可能会被删除。
o------o----o------o----o------------o (develop)
/ \
*----------o (main)
在此解决方案中,我们没有在 ClearCase 上使用中间分支,所有合并过程都发生在 Git 上。保留了 ClearCase 历史记录。唯一不好的地方就是最后合并需要锁开发分支。
@VonC,如有错误请随时修改我的答案
简介
这不仅仅是事实,对于少数人维护的大型项目,使用 ClearCase(而非 UCM)作为主要 SCM 是一个非常低效的解决方案。当它是企业标准时,我们坚持使用它,我们需要找到一个有效的解决方法。
ClearCase 的常用工作流由一个 master
分支、一个 develop
分支和几个新功能分支组成。
o--------o (feature)
/ \
----o--o---o-----o----o (develop)
/ \ \
*----------o---------o (main)
例子
其实我所说的特性也可以是简单的重构,比如项目内部的大量重命名。在这个例子中,因为 ClearCase 是以文件为中心的,所以我们总是需要一个临时分支(在非 UCM CC 中没有原子签入)。创建一个新分支是痛苦的,拥有正确的配置规范是一项艰巨的任务。从这里,我看到了两个解决方案:
成为公司并开始对所有文件进行大量检查。因为 SCM 环境与 ClearCase 服务器不在同一个站点上,所以一切都变慢了。我计算每个文件 2 秒,1k 文件计算 8 分钟。第一次喝咖啡休息后,我们开始工作并签入所有文件(又浪费了 8 分钟)。一些测试、新的大规模签出、错误修复、大量签入、合并到
develop
分支,最终我们删除了不再有用的feature
分支。在这个解决方案中,一切都很慢,消耗了大量的咖啡因,而且工作流程效率很低。我认为这不是一个好的解决方案。
因为我们想跟踪我们的更改,我们不想浪费时间 checkin/out 所有项目的文件,我们从 Git 初始化一个存储库快照视图。实际上,Git 存储库可以位于 ClearCase 之外的任何其他地方。这些更改是在 Git 的帮助下在本地进行的,一旦一切都完成,该项目就会通过
clearfsimport
推回到 ClearCase 上。在此之后,我们还需要合并feature
分支。这是在 CC 中完成的。然后可以删除功能分支。此解决方案需要大量操作。此外,如果我们拼错目标视图或忘记删除所有临时文件,
clearfsimport
可能会非常危险。最后但同样重要的是,最终合并必须在 CC 上完成。
快照视图
在我的示例中,我没有提到快照视图,因为它们与 Git 不兼容。根据时间戳识别的被劫持文件。如果我手动修改文件并恢复其原始修改日期,ClearCase 将看不到任何更改。这可能非常危险,下面的示例证明了这一点。
如果你不相信我,你可以试试这个:
stat -c 'touch --no-create -d "%y" "%n"' foo > restore_timestamp
echo "ClearCase will not see this" >> foo
source restore_timestamp
rm restore_timestamp
使用此机制,没有 Git 存储库可以驻留在 ClearCase 快照视图中。
分离 Git 存储库
我怀疑我们能否找到解决临时分支创建要求的方法。合并必须在 ClearCase 上完成,即使 Git 保留了所有内容。
我尝试广泛使用 Copy/Paste 来将完全独立的 Git 存储库与 ClearCase 同步。在最终合并之前,我 copy/paste 在新的 Git 分支中 develop
分支的当前状态,并尽快进行合并。最后,我使用 clearfsimport
将修改推回 develop
分支。
如果有人想在合并过程中访问该项目,此操作可能非常危险。为此,开发分支在运行过程中不得不被锁定或保留。不幸的是,这个额外的操作在 ClearCase 上非常耗时。
ClearCase“git checkout -b 功能”等效
在 Git 中,当我想创建一个新分支时,我只需键入:
git checkout -b feature
就是这样,我可以马上处理我的新功能。在 ClearCase 上,情况有些不同。
首先,我需要在要创建分支的位置放置一个标签。从 Windows 使用 Cygwin,我可以这样做:
LABEL=my_temporary_label
VOB=vob_name
cleartool mklbtype -global -nc lbtype:${LABEL}@\${VOB}
cleartool mklabel -replace ${LABEL} `cleartool find . -cview -print -nxn | awk '{printf "%s ", [=14=]}'`
cleartool find . -cview -type l -exec 'cleartool ls %CLEARCASE_XPN%' | \
perl -p -e 's/\/\//g' | \
perl -p -e 's/\r//g' | \
perl -e 'while(<>) {s@([.]/)(.*/)(.*-->\s*)@@;print;}' | \
xargs -n1 cleartool mklabel ${LABEL}
但是,我们需要小心,因为符号链接没有展开。
然后,必须创建一个分支:
mkbrtype –c "Temporary Branch" my_temporary_branch
要在此分支上工作,需要创建一个视图:
cleartool mkview -tag my_temporary_view \shared\path\to\viewStorage\my_temporary_view.vws
必须编辑配置规范:
element * CHECKEDOUT
element .../lost+found -none
element * .../develop_branch/LATEST
mkbranch develop_branch
element * /main/A_LABEL_WHERE_THE_BRANCH_IS_BRANCHED_ON
element * /main/LATEST
end mkbranch develop_branch
至此,分支创建完成。我们可以处理我们的功能。简单吧?
在Git,我一般一天创建3-5个分支。我不认为我可以用 ClearCase 做同样的事情。我错了吗?
讨论
所提出的两个解决方案都不太好,因为它们都需要在 ClearCase 上进行大量耗时的操作(创建分支、设置视图、签入、签出、合并、删除分支)。
我正在寻找一种不涉及复杂操作的解决方案。我仍然相信 Git 可能是一个很好的盟友,但 ClearCase 和 Git 如何协同工作?
我想我们可以使用一些脚本。我最近发现 git-cc 这可能是一个好的开始。不幸的是,这个项目还不成熟。
我还没有研究过这种方法,但我认为有一个解决方案,我们可以在 Git 中使用 ClearCase 快照视图。在进行任何更改之前必须保存每个文件的时间戳:
find . -type f -exec stat -c 'touch--no-create -d "%y" "%n"' {} \; > restore
从那里,我们可以在 Git 上工作,一旦到了将更改推送到 ClearCase 或只是从开发分支中提取更改的时间,就可以在所有文件上恢复原始时间戳,但自上次同步以来修改的文件:
source ./restore
git diff --name-only SHA1 SHA2 | xargs touch
问题
在 Whosebug 上,人们喜欢精确的问题,而不是基于主要观点的问题。因此,在这个相当长的介绍之后,我终于可以问我的问题了:
我已经尝试了很多不同的方法来改进我使用 ClearCase 的工作流程,但是使用 以文件为中心 SCM 的大型项目不是直截了当。我相信 Git 会有很大帮助,但我需要找到一个允许本地 git
存储库与 ClearCase 同步的工作流,并且如果可能的话,不需要临时分支。
可以吗?
Actually, what I call a feature could be also a simple refactoring, such as a massive renaming inside the project. In this example, and because ClearCase is file-centric, we always need a temporary branch (no atomic checkin in non-UCM CC).
Creating a new branch is painful and having the right config-spec is a struggling task
所以...不创建临时分支?
如果要与 Git 协作使用,仅在 Git 存储库中创建该功能分支,在 Git 存储库中进行最终合并,然后 clearfsimport 主 ClearCase 视图中的结果。
来自VonC
的可能解决方案在 VonC 的
我想通过一个例子来展示他的方法。我们从 ClearCase 上的这个配置开始:
o------o----o (develop)
/ \
*----------o (main)
想法是使用 Git 来促进新功能的开发,最终将合并到 develop
分支。
我们首先将 ClearCase 项目复制到本地文件夹并初始化一个 Git 存储库(如果 Git 存储库不存在)。
WORKSPACE=~/foo
cp `cleartool ls -r | grep '@@' | sed 's/@@.*$//'` $WORKSPACE
cd $WORKSPACE
git init
git add .
git commit -m "Initial commit"
git checkout -b feature
我们花了一些时间在自己的本地 Git 分支上开发该功能:
x----x--x---x----x (feature on Git)
/
x---------- (master on Git)
/
o------o----o------o----o (develop)
/ \
*----------o (main)
一天结束时,是时候从 ClearCase 同步可能的更改了:
git checkout master
git --ls-files | xargs rm
cd $CCVIEW
cleartool ls -r | grep '@@' | sed 's/@@.*$//' > $WORKSPACE/ccview
cd $WORKSPACE
cat ccview | xargs -n1 cp {} $WORKSPACE
cat ccview | xargs git add
git commit -m "Imported from CC"
现在我们已经在 feature
分支上进行了多次提交,并且 master
Git 分支与 ClearCase 同步。
x----x--x---x----x (feature on Git)
/
x-----------o (master on Git)
/ /
o------o----o------o----o (develop)
/ \
*----------o (main)
我们一定不要忘记在整个合并过程中锁定ClearCase View。这是为了防止其他开发人员看到他们自己的更改被 clearfsimport
删除。要锁定 ClearCase 分支很容易:
cleartool lock brtype:$BR_NAME
然后可以在 Git:
上完成合并git checkout master
git merge feature
feature
Git 分支与 master
合并。
x----x--x---x----x (feature on Git)
/ \
x-----------o--------o (master on Git)
/ /
o------o----o------o----o (develop)
/ \
*----------o (main)
可以将修改推回 ClearCase
OUT="$(mktemp -d)"
cp -v --parents `git ls-files | sed 's/[^ ]*\.gitignore//g'` $OUT
clearfsimport -comment 'clearfsimport' -rec -unco -nset $OUT $CVIEW
rm -rf $OUT
并且可以解除锁以重新授权分支上的更改
cleartool unlock brtype:$BR_NAME
。
x----x--x---x----x (feature on Git)
/ \
x-----------o--------o (master on Git)
/ / \
o------o----o------o----o------------o (develop)
/ \
*----------o (main)
除非我们需要继续,否则 Git 存储库和本地工作区可能会被删除。
o------o----o------o----o------------o (develop)
/ \
*----------o (main)
在此解决方案中,我们没有在 ClearCase 上使用中间分支,所有合并过程都发生在 Git 上。保留了 ClearCase 历史记录。唯一不好的地方就是最后合并需要锁开发分支。
@VonC,如有错误请随时修改我的答案