ClearCase希望在交付到备用目标后合并未更改的文件

时间:2009-07-07 07:52:53

标签: clearcase clearcase-ucm

将Rational ClearCase v.7.0.1.1与UCM一起使用时,我在使用ClearCase的“从流交换到备用目标”功能时遇到了问题。

想象一下,我们有一个项目集成流和两个从它派生的开发人员流A和B.现在我在流A中更改了一个文件。我希望delevoper拥有流B能够使用我的工作而不必将文件传递到集成流,所以我从流A传递到备用目标流B. / p>

到目前为止,这么好。我继续对文件进行另一次更改,但是流B开发人员不需要进行此更改,因此我不会将其发送给他。

经过一段时间,我将工作交付给主要的集成流。这很好用,虽然我想知道为什么ClearCase将合并标记为正常的“合并”而不是“合并(平凡)” - 除了我之外没有人对文件进行更改。

交付后,将在主要集成流上创建新基线。

当开发人员B试图改变他的流时,真正的问题就出现了。由于开发人员B从未对文件进行任何更改,因此我希望合并是一个简单的合并,无需进行任何交互。但是,开发人员B被迫以图形方式解决该文件上的合并冲突,让他在集成流上的基本版本,我提供给他的版本和我提供给集成流的版本之间进行选择。

在解决合并并完成rebase后,开发人员B想要执行到主集成流的交付时,会出现混淆。除了我最初交给他的活动之外,他还被要求提供一项名为rebase _...的活动,我绝不会期望这项活动可以交付。

我在这里遗漏了什么吗?我们是否错误地使用ClearCase或者这是一个已知的限制/错误?有没有人体验过这个功能?

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

实际上,当我查看版本树时,在rebase期间冲突的来源是明确的:

version tree with conflict

当您重新阅读ClearCase 3-way merge works的方式时,您会发现需要返回版本树才能找到共同的祖先:

  • 来源(Int / 2)
  • 目的地(B / 1)

那个共同的祖先是Int / 1

现在有可能是这两个版本之间的公共线路发生了变化:

  • 最后一个rebase(Int / 2)的来源来自A / 3
  • 最后一个rebase(B / 1)的目的地来自A / 2
  • 共同祖先(Int / 1)来自A / 1

如果在A / 2和A / 3中修改了公共线(来自A / 1)......那么就有理由在那里手动合并解决方案!

(我现在正在测试这个)


知道了!冲突实现了!

继续我的previous experiment

让我们在流A中创建一个新的modif:

M:\vonc_test_dat_a\adev\test>ct co -nc aFile.txt
M:\vonc_test_dat_a\adev\test>echo modif by A to B>>aFile.txt
M:\vonc_test_dat_a\adev\test>ct ci -nc aFile.txt

M:\vonc_test_dat_a\adev\test>type aFile.txt
first line done on Int
Second line from Int
Addition by A to be delivered to B first
Modification by A to be delivered to Int, B does not need it
modif by A to B

直接向B发送:

M:\vonc_test_dat_a\adev\test>ct deliver -to vonc_test_dat_b -target Test_DAT_B@\myPVob -cact -gmerge -force
Changes to be DELIVERED to non-default target stream in current project "Test_DeliverToAlternateTarget":
          FROM: stream "Test_DAT_A"
          TO: stream "Test_DAT_B"
Using target view: "vonc_test_dat_b".
Activities included in this operation:
        activity:test_dat_a@\myPVob   vonc        "test_dat_a"
Trivial merge: "M:\vonc_test_dat_b\adev\test\aFile.txt" is same as base "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\Test_DAT_A\2".
Copying "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\Test_DAT_A\3" to output file.
Deliver has merged

M:\vonc_test_dat_a\adev\test>ct deliver -target Test_DAT_B@\myPVob -cact -complete -force

(琐事合并)

现在让我们COMPLETELTY更改该文件的内容:

M:\vonc_test_dat_a\adev\test>ct co -nc aFile.txt
M:\vonc_test_dat_a\adev\test>echo change first line>aFile.txt
M:\vonc_test_dat_a\adev\test>ct ci -nc aFile.txt

M:\vonc_test_dat_a\adev\test>type aFile.txt
change first line

交付给Int,在交付后立即投入新基线:

M:\vonc_test_dat_a\adev\test>ct deliver -force
M:\vonc_test_dat_a\adev\test>ct deliver -force -complete
M:\vonc_test_dat_a\adev\test>ct mkbl -comp ADV_TST@\myPVob -view vonc_test_dat_int TST_DAT1.2.0

(另一个微不足道的合并)

来自B的rebase怎么样?

M:\vonc_test_dat_b\adev\test>ct rebase -bas TST_DAT1.2.0
Advancing to baseline "TST_DAT1.2.0" of component "ADV_TST"
Updating rebase view's config spec...
Creating integration activity...
Setting integration activity...
Merging files...
Checked out "M:\vonc_test_dat_b\adev\test\aFile.txt" from version "\main\Test_DAT_Int\Test_DAT_B\3".
  Attached activity:
    activity:rebase.Test_DAT_B.20090707.163300@\myPVob  "rebase Test_DAT_B on 07/07/09 4:33:00 PM."
Needs Merge "M:\vonc_test_dat_b\adev\test\aFile.txt" [to \main\Test_DAT_Int\Test_DAT_B\CHECKEDOUT from \main\Test_DAT_Int\4 base \main\T
est_DAT_Int\3]
********************************
<<< file 1: M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\3
>>> file 2: M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\4
>>> file 3: M:\vonc_test_dat_b\adev\test\aFile.txt
********************************
---------[changed 1-4 file 1]----------|---------[changed to 1 file 2]---------
first line done on Int                 | change first line
Second line from Int                   |-
Addition by A to be delivered to B fir+|
Modification by A to be delivered to I+|
                                      -|
*** Automatic: Applying CHANGE from file 2 [line 1]
============
============
-----------[after 4 file 1]------------|----------[inserted 5 file 3]----------
                                      -| modif by A to B
                                       |-
Do you want the INSERTION made in file 3?  [yes] no
============
============
Output of merge is in "M:\vonc_test_dat_b\adev\test\aFile.txt".
Recorded merge of "M:\vonc_test_dat_b\adev\test\aFile.txt".
Build and test are necessary to ensure that any merges and configuration changes were completed correctly.
When build and test are confirmed, run "cleartool rebase -complete".

你有它:来自共同祖先的两个不相容的变化之间的一个很好的冲突。

以下图片说明:

conflict during merge

答案 1 :(得分:2)

我对此冲突感到惊讶:因为ClearCase确实将流A中的合并注册到B,除非流B没有与流A相同的基础基线(分支或初始标签的起点)。

  

除了我最初交付给他的活动之外,他还被要求提供名为rebase _...的活动,我绝不会期望这项活动可以交付。

当您从Int重新绑定到B时,您会创建一个自动“时间轴”,将所有活动链接在一起 这意味着,在下一次交付期间,即使没有为此变更集中的所有版本执行合并,B也必须提供rebase。


先说几句:

  • 您可能希望避免创建附加到资源的流(开发人员“A”,开发人员“B”):如果他们正在为相同的全局“开发工作”处理单独的文件集,那么应该只有一个Stream_FeatureF代表手头的任务 然后A和B应该看到附加到该流的相同分支的相同LATEST(无需从一个流传送到另一个流) 如果B不断打破A的工作,那么只有这样才能为破坏性子特征创建一个子流,这个子特征不能与主要特征“F”同时开发。

  • 当合并为 trivial 时,递送/ rebase GUI不会显示“是(平凡)”(请参阅​​下面的测试)。这并不意味着合并不是微不足道的(意味着基数与来源或目的地相同,请参阅 core concepts

  • 我的测试下面尊重您描述的合并工作流程,但只显示了一些简单的合并 什么可以解释非平凡的将是“邪恶的双胞胎”(一个文件中添加的文件,但在另一个流中从头开始重新创建,具有相同的名称)


好吧,让我们测试一下,假设一个Vob“adev”(代表“开发架构”,我的团队存放其工具),在\ adev \ test中使用UCM组件ADV_TST。 Windows上的ClearCase7.0.1(虽然Vob实际上是在Unix上)

让我们从一个Test项目开始,一个Integration流和一个空的测试组件:

M:\>ct mkproj -in folder:ADV_Tests@\myPVob Test_DeliverToAlternateTarget@\myPVob
M:\>ct mkstream -int -in Test_DeliverToAlternateTarget@\myPVob Test_DAT_Int@\myPVob
Created stream "Test_DAT_Int".
M:\>ct mkview -tag vonc_test_dat_int -stream Test_DAT_Int@\myPVob -stg hostname_ccstg_c_views
M:\vonc_test_dat_int\adev\test>ct rebase -bas ADV_TST0.0.0
Adding baseline "ADV_TST0.0.0" of new component "ADV_TST"
M:\vonc_test_dat_int\adev\test>ct rebase -complete

让组件可写:

M:\vonc_test_dat_int\adev\test>ct chproj -amodcomp component:ADV_TST@\myPVob Test_DeliverToAlternateTarget@\myPVob
M:\vonc_test_dat_int\adev\test>ct chstream -generate Test_DAT_Int@\myPVob
M:\vonc_test_dat_int\adev\test>ct setcs -stream

A将在Int上创建一个文件,添加它,修改它,然后放一个基线:

M:\vonc_test_dat_int\adev\test>ct mkact test_dat_int
M:\vonc_test_dat_int\adev\test>echo first line done on Int>aFile.txt
M:\vonc_test_dat_int\adev\test>ct co -nc .
M:\vonc_test_dat_int\adev\test>ct mkelem -nc aFile.txt
M:\vonc_test_dat_int\adev\test>ct ci -nc .
M:\vonc_test_dat_int\adev\test>ct ci -nc aFile.txt

M:\vonc_test_dat_int\adev\test>ct co -nc aFile.txt
M:\vonc_test_dat_int\adev\test>echo Second line from Int>>aFile.txt
M:\vonc_test_dat_int\adev\test>ct ci -nc aFile.txt

M:\vonc_test_dat_int\adev\test>type aFile.txt
first line done on Intct mkview vonc_
Second line from Int

M:\vonc_test_dat_int\adev\test>ct mkbl -comp ADV_TST@\myPVob TST_DAT1.0.0
Created baseline "TST_DAT1.0.0" in component "ADV_TST".

现在,让我们创建两个子流,每个开发人员一个(虽然可能被认为是“不良做法”),都使用相同的基线TST_DAT1.0.0初始化:

M:\vonc_test_dat_int\adev\test>ct mkstream -in Test_DAT_Int@\myPVob Test_DAT_A@\myPVob
M:\vonc_test_dat_int\adev\test>ct mkstream -in Test_DAT_Int@\myPVob Test_DAT_B@\myPVob
M:\vonc_test_dat_int\adev\test>ct mkview -tag vonc_test_dat_a -stream Test_DAT_A@\myPVob -stg hostname_ccstg_c_views
M:\vonc_test_dat_int\adev\test>ct mkview -tag vonc_test_dat_b -stream Test_DAT_B@\myPVob -stg hostname_ccstg_c_views
M:\vonc_test_dat_int\adev\test>ct rebase -view vonc_test_dat_a -bas TST_DAT1.0.0
M:\vonc_test_dat_int\adev\test>ct rebase -view vonc_test_dat_a -complete
M:\vonc_test_dat_int\adev\test>ct rebase -view vonc_test_dat_b -bas TST_DAT1.0.0
M:\vonc_test_dat_int\adev\test>ct rebase -view vonc_test_dat_b -complete

A将对他的流A进行修改,以便传递给B:

M:\vonc_test_dat_a\adev\test>ct mkact test_dat_a
M:\vonc_test_dat_a\adev\test>ct co -nc aFile.txt
Created branch "Test_DAT_A" from "aFile.txt" version "\main\Test_DAT_Int\2".
M:\vonc_test_dat_a\adev\test>echo Addition by A to be delivered to B first>>aFile.txt
M:\vonc_test_dat_a\adev\test>ct ci -nc aFile.txt

直接从流A到B:

M:\vonc_test_dat_a\adev\test>ct deliver -to vonc_test_dat_b -target Test_DAT_B@\myPVob -cact -gmerge
Changes to be DELIVERED to non-default target stream in current project "Test_DeliverToAlternateTarget":
          FROM: stream "Test_DAT_A"
          TO: stream "Test_DAT_B"
Using target view: "vonc_test_dat_b".
Activities included in this operation:
        activity:test_dat_a@\myPVob   vonc        "test_dat_a"
Created branch "Test_DAT_B" from "M:\vonc_test_dat_b\adev\test\aFile.txt" version "\main\Test_DAT_Int\2".
Checked out "M:\vonc_test_dat_b\adev\test\aFile.txt" from version "\main\Test_DAT_Int\Test_DAT_B\0".
  Attached activity:
    activity:deliver.Test_DAT_A.20090707.123738@\myPVob  "deliver Test_DAT_A on 07/07/09 12:37:38 PM."
Needs Merge "M:\vonc_test_dat_b\adev\test\aFile.txt" [to \main\Test_DAT_Int\Test_DAT_B\CHECKEDOUT from \main\Test_DAT_Int\Test_DAT_A\1 b
ase \main\Test_DAT_Int\2]
Trivial merge: "M:\vonc_test_dat_b\adev\test\aFile.txt" is same as base "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\
2".
Copying "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\Test_DAT_A\1" to output file.
Deliver has merged
M:\vonc_test_dat_a\adev\test>ct deliver -target Test_DAT_B@\myPVob -force -complete

我确认GUI没有显示琐碎,尽管同一次发送的文字输出确实提到了 Trivial merge ......

继续处理'aFile.txt'并将其传递给Int:

M:\vonc_test_dat_a\adev\test>ct co -nc aFile.txt
M:\vonc_test_dat_a\adev\test>echo Modification by A to be delivered to Int, B does not need it>>aFile.txt
M:\vonc_test_dat_a\adev\test>ct ci -nc aFile.txt

M:\vonc_test_dat_a\adev\test>ct deliver
Changes to be DELIVERED to default target stream in project "Test_DeliverToAlternateTarget":
          FROM: stream "Test_DAT_A"
          TO: stream "Test_DAT_Int"
Using target view: "vonc_test_dat_int".
Activities included in this operation:
        activity:test_dat_a@\myPVob   vonc        "test_dat_a"
Do you wish to continue with this deliver operation?  [no] yes
Checked out "M:\vonc_test_dat_int\adev\test\aFile.txt" from version "\main\Test_DAT_Int\2".
  Attached activity:
    activity:deliver.Test_DAT_A.20090707.124108@\myPVob  "deliver Test_DAT_A on 07/07/09 12:41:08 PM."
Needs Merge "M:\vonc_test_dat_int\adev\test\aFile.txt" [to \main\Test_DAT_Int\CHECKEDOUT from \main\Test_DAT_Int\Test_DAT_A\2 base \main
\Test_DAT_Int\2]
Trivial merge: "M:\vonc_test_dat_int\adev\test\aFile.txt" is same as base "M:\vonc_test_dat_int\adev\test\aFile.txt@@\main\Test_DAT_
Int\2".
Copying "M:\vonc_test_dat_int\adev\test\aFile.txt@@\main\Test_DAT_Int\Test_DAT_A\2" to output file.
Deliver has merged
M:\vonc_test_dat_a\adev\test>ct deliver -force -complete

(另一个微不足道的合并)

让我们在Int:

上放一个基线
M:\vonc_test_dat_a\adev\test>ct mkbl -nc -view vonc_test_dat_int TST_DAT1.1.0
Created baseline "TST_DAT1.1.0" in component "ADV_TST".
Begin incrementally labeling baseline "TST_DAT1.1.0".
Done incrementally labeling baseline "TST_DAT1.1.0".

现在,我们切换到B,他开始在另一个文件上做一些自己的小工作:

M:\vonc_test_dat_b\adev\test>ct mkact test_dat_b
M:\vonc_test_dat_b\adev\test>echo myFile by B>aFileByB.txt
M:\vonc_test_dat_b\adev\test>ct co -nc .
M:\vonc_test_dat_b\adev\test>ct mkelem -nc aFileByB.txt
M:\vonc_test_dat_b\adev\test>ct ci -nc aFileByB.txt
M:\vonc_test_dat_b\adev\test>ct ci -nc .

然后,突然之间,他不得不用他在Int中整合的东西来改变他的工作:

M:\vonc_test_dat_b\adev\test>ct rebase -bas TST_DAT1.1.0
Advancing to baseline "TST_DAT1.1.0" of component "ADV_TST"
Updating rebase view's config spec...
Creating integration activity...
Setting integration activity...
Merging files...
Checked out "M:\vonc_test_dat_b\adev\test\aFile.txt" from version "\main\Test_DAT_Int\Test_DAT_B\1".
  Attached activity:
    activity:rebase.Test_DAT_B.20090707.125044@\myPVob  "rebase Test_DAT_B on 07/07/09 12:50:44 PM."
Needs Merge "M:\vonc_test_dat_b\adev\test\aFile.txt" [to \main\Test_DAT_Int\Test_DAT_B\CHECKEDOUT from \main\Test_DAT_Int\3 base \main\T
est_DAT_Int\Test_DAT_A\1]
Trivial merge: "M:\vonc_test_dat_b\adev\test\aFile.txt" is same as base "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\
Test_DAT_A\1".
Copying "M:\vonc_test_dat_b\adev\test\aFile.txt@@\main\Test_DAT_Int\3" to output file.
Output of merge is in "M:\vonc_test_dat_b\adev\test\aFile.txt".
Recorded merge of "M:\vonc_test_dat_b\adev\test\aFile.txt".

M:\vonc_test_dat_b\adev\test>type aFile.txt
first line done on Int
Second line from Int
Addition by A to be delivered to B first
Modification by A to be delivered to Int, B does not need it

M:\vonc_test_dat_b\adev\test>ct rebase -complete

根本没有冲突:琐碎合并

B继续处理他的文件:

M:\vonc_test_dat_b\adev\test>ct setact test_dat_b
M:\vonc_test_dat_b\adev\test>ct co -nc aFileByB.txt
M:\vonc_test_dat_b\adev\test>echo a modif by B to be delivered to Int>>aFileByB.txt
M:\vonc_test_dat_b\adev\test>ct ci -nc aFileByB.txt

然后他将所有工作交给Int:

M:\vonc_test_dat_b\adev\test>ct deliver -cact
cleartool: Error: Activity "deliver.Test_DAT_A.20090707.123738" must be added to activity list to preserve baseline order in stream.
cleartool: Error: Activity "rebase.Test_DAT_B.20090707.125044" must be added to activity list to preserve baseline order in stream.
cleartool: Error: The list of activities specified is incomplete.
cleartool: Error: Unable to deliver selected activities.
cleartool: Error: Unable to deliver stream "Test_DAT_B".

我确认他必须选择所有活动(而不仅仅是他的):在最后一个rebase期间设置的时间轴已将所有活动链接在一起。
即使没有与活动“deliver.Test_DAT_A.20090707.123738”和活动“rebase.Test_DAT_B.20090707.125044”进行合并,也必须包含它们:

M:\vonc_test_dat_b\adev\test>ct deliver
Changes to be DELIVERED to default target stream in project "Test_DeliverToAlternateTarget":
          FROM: stream "Test_DAT_B"
          TO: stream "Test_DAT_Int"
Using target view: "vonc_test_dat_int".
Activities included in this operation:
        activity:deliver.Test_DAT_A.20090707.123738@\myPVob   vonc        "deliver Test_DAT_A on 07/07/09 12:37:38 PM."
        activity:test_dat_b@\myPVob   vonc        "test_dat_b"
        activity:rebase.Test_DAT_B.20090707.125044@\myPVob    vonc        "rebase Test_DAT_B on 07/07/09 12:50:44 PM."
Do you wish to continue with this deliver operation?  [no]

  Attached activity:
    activity:deliver.Test_DAT_B.20090707.131614@\myPVob  "deliver Test_DAT_B on 07/07/09 1:16:14 PM."
Needs Merge "M:\vonc_test_dat_int\adev\test" [to \main\Test_DAT_Int\CHECKEDOUT from \main\Test_DAT_Int\Test_DAT_B\1 base \main\Test_DAT_
Int\1]
********************************
<<< directory 1: M:\vonc_test_dat_int\adev\test@@\main\Test_DAT_Int\1
>>> directory 2: M:\vonc_test_dat_int\adev\test@@\main\Test_DAT_Int\Test_DAT_B\1
>>> directory 3: M:\vonc_test_dat_int\adev\test
********************************
-----------[ directory 1 ]-------------|---------[ added directory 2 ]---------
                                      -| aFileByB.txt  --07-07T12:50 vonc
*** Automatic: Applying ADDITION from directory 2
Recorded merge of "M:\vonc_test_dat_int\adev\test".
Created branch "Test_DAT_Int" from "M:\vonc_test_dat_int\adev\test\aFileByB.txt" version "\main\0".
Checked out "M:\vonc_test_dat_int\adev\test\aFileByB.txt" from version "\main\Test_DAT_Int\0".
  Attached activity:
    activity:deliver.Test_DAT_B.20090707.131614@\myPVob  "deliver Test_DAT_B on 07/07/09 1:16:14 PM."
Needs Merge "M:\vonc_test_dat_int\adev\test\aFileByB.txt" [to \main\Test_DAT_Int\CHECKEDOUT from \main\Test_DAT_B\2 base \main\0]
Trivial merge: "M:\vonc_test_dat_int\adev\test\aFileByB.txt" is same as base "M:\vonc_test_dat_int\adev\test\aFileByB.txt@@\main\0".

Copying "M:\vonc_test_dat_int\adev\test\aFileByB.txt@@\main\Test_DAT_B\2" to output file.
Deliver has merged
M:\vonc_test_dat_b\adev\test>ct deliver -complete