1

简短的:

您如何确保任何 DVCS 的分布式存储库克隆中没有未保存的工作?

我正在专门为 Mercurial 考虑这一点,但它也适用于 git、bzr 等。

细节:

回到糟糕的过去,我曾经运行可能会执行相当于 - 伪代码的 cron 作业,因为我可能不记得 CVS 命令:

find all checked out CVS trees
   do a cvs status command (which I think is something like cvs update -n?) 
   | grep '^M' to find all modified files not yet committed to the central repo

(这些日子很糟糕(1)因为我们使用的是 CVS,(2)因为有时我是负责制作 sue 的人,没有丢失任何东西。好吧,那最后不是那么糟糕,但正在溃烂。)

问:对于像 Mercurial 这样的现代 DVCS 系统,我如何进行等效操作。我认为这很容易,但仔细检查会发现缺少一些部分:

我开始做类似的事情

find all ...path/.hg directories, and then look at ...path
    do hg status - look at the output  // this is easy enough
    do hg outgoing // this is where it gets interesting

你可能认为做一个 hg 传出就足够了。但不一定。

考虑:

cd workspace-area
hg clone master repo1
hg clone repo1 repo2
rm -rf repo1
hg clone repo2 repo1

现在repo1的默认路径是repo2,反之亦然。

当然,如果您有正确的工作流程,就不会发生这种情况。如果你只从你上游的东西克隆,永远不要从同龄人那里克隆。但是...轻量级克隆是顶级做 DVCS 的部分原因。另外,它已经发生在我身上。

为了处理这个问题,我通常在某个地方有一个 hg 路径,在我的 ~/.hgrc 中设置,设置为某个项目主 URL。这很好用 - 对于那个项目。如果你有很多很多项目,那就不太好了。即使您称它们为 project1-master project2-master 等,它们也会有很多。如果由于想要在项目之间共享的库而导致子存储库激增,则更糟糕的是。

此外,这必须在用户的 .hgrc 中。或网站 .hgrc。对于可能没有设置 .hgrc 的人来说不是很好——比如一个不知道他系统上几十个(或数百个)项目的来龙去脉的管理员 - 但他仍然希望做他的用户寻找陈旧工作的青睐。(他们可能已经预料到了。)或者,如果您只是想提供有关如何执行此操作的标准说明。

我考虑将项目(或列表)的一些标准主存储库的名称放入文本文件中,并签入存储库。说 repo/.hg_master_repos。这看起来可能有效,虽然它有一些问题(您可能只看到全局项目主,而不是额外的本地项目主。我不想解释更多。)。

但是......在我这样做之前,有没有这样做的标准方法?


顺便说一句,这是我到目前为止所拥有的:

#!/usr/bin/perl
use strict;

# check to see if there is any unsaved stuff in the hg repo(s) on the command line

# -> hg status, looking for Ms, etc.
#        for now, just send it all to stdout, let the user sort it out

# -> hg outgoing
# issue: who to check outgoing wrt to?
#   generic
#      a) hg outgoing
#           but note that I often make default-push disabled
#           also, may not point anywhere useful, e.g
#               hg clone master r1
#               hg clone r1 r2
#               rm -rf r1
#               hg clone r2 r1`
#           plus, repos that are not clones, masters...
#      b) hg outgoing default-push
#      c) hg outgoing default
#   various repos specific to me or my company


foreach my $a ( @ARGV ) {
    print "**********  $a\n";
    $a =~ s|/\.hg$||;
    if( ! -e "$a/.hg" ) {
        print STDERR "Warning: $a/.hg dos not exist, probably not a Mercurial repository\n";
    }
    else {
        foreach my $cmd (
                 "hg status",
                 # generic
                 "hg outgoing",
                 "hg outgoing default-push",
                 "hg outgoing default",
                 # specific
                 "hg outgoing PROJECT1-MASTER",
                 "hg outgoing MY-LOCAL-PROJECT1-MASTER",
                 "hg outgoing PROJECT2-MASTER",
                 # maybe go through all paths?
                 # maybe have a file that contains some sort of reference master?
                )
          {
              my $cmd_args = "$cmd -R $a";
              print "=======  $cmd_args\n";
              system($cmd_args);
          }
    }
}

正如你所看到的,我没有用任何东西来装饰它来解析它所得到的东西——只是让用户,我,来关注它。

但只是做

find ~ -name '*.hg' | xargs ~/bin/hg-any-unsaved-stuff.pl

发现了很多我不知道的可疑未保存的东西。

hg status 报告的未保存的旧更改非常可疑。传出报告的未推动工作是可疑的,但对于认为克隆是分支的人来说,这可能不是那么糟糕。但是,我不希望有一个分叉的克隆永远存在,而是将事物放在分支上,以便有人可以通过从一个地方克隆来查看所有历史。

底线:

是否有一种标准方法可以找到未保存的工作、未签入和/或未推送的工作,这种方法不易受到我上面提到的各种周期的影响?

在某处的文件中记录“真实”项目主存储库是否有一些约定?

嗯...我想如果在某处记录了推送和克隆魔杖签入所涉及的存储库,我可以猜测正确的项目大师可能是什么。

4

2 回答 2

1

以下是您可以执行的操作:

  1. 确定服务器上可能的中央存储库。

  2. 迭代客户端上的存储库以将它们与中央存储库匹配。

  3. hg outgoing针对您找到的中央存储库运行。

更详细一点:

  1. 我假设您的存储库有一个中心位置,否则您的问题将变得毫无意义。现在,可以通过根变更集来识别存储库。此变更集将是修订版零,您可以获得完整的变更集,如下所示:

    $ hg log -r 0 --template "{node}"
    

    (node, URL)在服务器上运行脚本,将配对列表转储到客户端可访问的文件中。URL 将成为推送目标。

  2. 在客户端上运行脚本,首先(node, URL)从服务器下载列表,然后识别所有本地存储库和服务器上的相应推送 URL。

  3. hg outgoing URL使用您在上一步中找到的 URL运行。您可以(并且应该!)使用完整的 URL,hg outgoing以避免依赖于客户端上完成的任何本地配置。这样您就可以避免处理路径,default并且default-push由于 URL 指向服务器,因此您知道这是一个可以比较的好 URL。

    如果服务器有多个相同存储库的克隆,那么将有几个不同的 URL 可供选择。然后,您可以全部尝试并使用具有最少传出变更集的报告,或者您可以通过在服务器端组合克隆(通过将所有克隆中的变更集拉到单个存储库中)来回避问题,然后与此组合存储库进行比较。

当您在客户端上运行脚本时,您可能有一些本地存储库并且在服务器上不存在。您的脚本应该处理这些:它可能应该向开发人员发送一封电子邮件,要求他在服务器上创建存储库。

最后,一个存储库可能有多个根变更集。以上仍然可以很好地工作:所有以正常方式完成的克隆将在服务器和客户端上保持修订为零相同。因此,即使有多个根,脚本也会正确地将客户端 repo 与服务器 repo 匹配。

仅当开发人员运行类似的操作hg clone -r the-other-root ...时,上述操作才会失败,因为另一个根现在变为修订版零。因此,存储库将被视为本地存储库。无论如何,您的脚本都应该处理它,所以这没什么大不了的。

于 2012-07-23T02:11:03.327 回答
0

如果您只关心数据丢失并且您正在使用 git,那么只需创建一个存储库。将所有创建的存储库作为遥控器添加到该存储库并运行

git fetch --all

这将有效地备份所有存储库中的所有数据。它还备份所有引用的当前快照。

于 2012-07-21T12:26:24.443 回答