如何知道本地仓库与远程仓库不同,没有提取?

时间:2014-01-26 10:12:29

标签: git git-remote git-diff git-commands

我有几十个repos,如果发生任何差异,我的脚本应该更新它们,新提交,新标记,新分支。在我的情况下,Fetch对于几十个回购来说有点慢,我想知道是否有任何快速命令可以满足我的要求。

3 个答案:

答案 0 :(得分:5)

您可以使用git ls-remote plumbing命令获取没有fetch的遥控器状态。

在这里,让我们使用git本身作为轻量级数据库来跟踪遥控器的状态。

将以下内容放入脚本中;为方便起见,您可以稍后将其作为git别名shell函数启用。在您的仓库内运行。

REMOTE_SUM=$(git ls-remote --tags --heads 2>/dev/null | git hash-object --stdin)
if git cat-file -e $REMOTE_SUM
then
    echo Remote check-summed up-to-date.
else
    echo Remote changed, fetching...
    git ls-remote --tags --heads 2>/dev/null | \
        git hash-object -w --stdin &>/dev/null
    git fetch
fi

<子> 省略了一些必要的错误检查,并且为了清楚起见重复了代码。

解释

列出所有带git ls-remote --tags --heads的远程提示会生成输出,例如:

From /home/user/tmp/repo2
777201715768a4d82f374f7224e68164a916ac1f        refs/heads/bar
78981922613b2afb6025042ff6bd878ac1994e85        refs/heads/master
...

反过来,我们通过git hash-object --stdin将远程仓库的上述图片作为单个哈希哈希并检查我们之前是否通过使用git cat-file -e查询git中的哈希值来查看它。如果我们还没有看到它,那么远程图片必须已经改变,我们首先在git中用git hash-object -w记录它,以适应拉动和提交遥控器之间的比赛,然后继续获取遥控器。

可以将其与git预取功能pre-fetch hook functionality in git集成,但这超出了此答案的范围。

附录

请注意,上面的内容会在git中生成松散的对象,偶尔需要使用git gc--prune明确地进行垃圾回收。

此外,只要提交不是故意重新排列,分支提示保持不变,上述工作就应该有效。这将是/非常罕见的/并且反对改变推送状态的git指导,但是,嘿,可能发生的最糟糕的事情是你跳过了一个提取。

另请注意,ls-remote适用于单个遥控器。要使用多个遥控器,您必须通过生成git remote show的遥控器列表来扩展脚本,并依次处理每个遥控器。

答案 1 :(得分:2)

您无权访问origin服务器

您不能仅使用git

修改

根据另一个答案,git ls-remote可能对您有用。

但是,正如您必须ls-remote所有存储库一样,如果您的问题是网络延迟,则无法使用ls-remote解决。


您可以访问origin服务器

  1. 在服务器上的repo上写入时设置挂钩。钩子会将repo标记为被修改。例如,您可以在服务器上的某处创建repo_name__MODIFIED文件。
  2. 在更新仓库之前,请检查仓库是否已修改。对于给定的示例,请检查服务器上是否存在文件repo_name__MODIFIED
  3. 如果修改了repo,则在更新repo之前,将其标记为未修改(在获取之前)。在我们的示例中,只需删除服务器上的repo_name__MODIFIED文件。

  4. 注意

    为什么抓取这么长时间? git只会获取新的提交,如果origin没有修改,它应该非常快!

答案 2 :(得分:0)

如果您使用git clonegit remote add $REMOTE_NAME $REMOTE_URL设置了本地存储库,则需要将本地分支机构与远程对等分支机构进行比较所需的所有信息(在您上次{{1}时) })已经存在了。

如果您设置了远程跟踪分支,git fetch会告诉您是否与您正在跟踪的远程分支存在差异,如下所示。

git status

还有一个可解析的形式:

$ git status
On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   perl/Makefile.am

no changes added to commit (use "git add" and/or "git commit -a")