在不克隆 git 仓库的情况下浏览和展示文件

132

有没有一种方法可以在不先克隆git仓库的情况下浏览和显示其中的文件?我可以使用以下命令在svn中执行此操作:

svn ls /path/to/repo 
svn cat /path/to/repo/file-in-repo

我可以尝试使用git show,但是执行:

git show /path/to/repo
git show HEAD:/path/to/repo

会导致:

fatal: Not a git repository
7个回答

88

您需要的命令是git ls-remote,它允许您获取有关远程存储库的一些信息,但您无法显示历史记录、列出目录或任何类似的内容:它基本上只允许您以非常高级别的方式查看远程对象(例如,您可以查看当前的头和标签)。

如果我理解正确,唯一真正的方法是使用ssh运行远程命令并返回结果,例如:

ssh me@otherhost "cd repo && git log -n 10"

如果他们能够添加你想要的功能,那将是一个可爱的功能,但从我所读到的来看,这并不容易,因为获取历史记录等需要大量与 Git 本地相关的信息,而此时最好直接进行 Git Fetch。


17
使用 git clone 命令的一个技巧是可以通过添加参数 --depth 1 来仅获取单个版本。这样可以避免获取大量的历史记录,并且足以回答如“哪些文件存在于版本号为abcdef1234567890的版本中?”的问题。 - ctrueden

24

Git 是一种分布式版本控制系统,而 Subversion 则是一种集中式(客户端-服务器)版本控制系统。它们的工作方式不同。请阅读我的答案,解释这种差异对 git 相当于 svn status -u 的问题 在 StackOverflow 上的影响。

再强调一遍:在集中式版本控制系统(如 CVS 或 Subversion)中,几乎所有命令都在服务器上处理,并涉及网络。只有极少数命令是在本地执行的。请注意,为了获得“svn status”和“svn diff”的良好性能,Subversion 在客户端存储已检出版本的 'pristine copy',以避免对这些常见操作进行网络传输(这意味着 Subversion checkout 至少等于工作目录大小的两倍)。

在分布式版本控制系统(如 Git、Mercurial 或 Bazaar)中,你拥有整个仓库的本地副本(clone),几乎所有命令都在客户端执行。只有极少数命令需要连接到其他仓库(服务器)。

可以在服务器上执行的命令数量是有限的。

  • 你可以使用 "git ls-remote <URL>" 列出远程引用。
  • 如果远程服务器启用了它,则可以使用 "git archive --remote=<URL> HEAD" 获取仓库(部分)快照。
  • 你可以使用 "git clone --depth=1 <URL>" 只克隆最后几个提交(所谓的“浅克隆”)。
  • 如果服务器提供 git web 接口到仓库,你可以使用它来浏览。

53
尽管你的观点是正确的,但如果你在没有先克隆远程仓库的情况下浏览它,那么显然你已经决定放弃 Git 的离线功能。鉴于这一点,我认为没有理由假装这不会是某些事情的有用特性,例如,一个本地客户端,可以让你在本地浏览远程仓库的文件内容。 - LadyCailin
16
同意,Jakub 所持的立场非常严格。为了指出这一点,失去声誉不止一次是值得的。 - ctpenrose
13
我不喜欢“要适应这种语气”,但是读到最后,我找到了解决当前问题的方法——想看看110仓库里有什么,我只有一个git账号,但没有SSH或shell访问权限,而且这些仓库都很大,大约12GB左右。因此,使用最小化深度进行克隆可以帮助只查看最近的有趣历史记录,并尽可能使git仓库变小。 - Henning
3
如果在代码审查工具中只需要日志记录而不是整个代码库的情况下,这样的功能就非常有用。 - Lukasz Lenart
2
想象一下为基于Yocto的项目创建发布说明/更改日志文档。在您的git log中看到了很多“bump version”提交,如果您想知道实际发生了什么变化,使用这种“习惯于此”的方法,您必须去克隆每个通常只在构建服务器上克隆的存储库。你知道,这不是很方便。因此,如果git服务器可以执行log或提取单个文件,那将真正有帮助。特别是考虑到除了“习惯于此”态度外,没有任何东西可以阻止它这样做。 - Alexander Amelkin
显示剩余4条评论

17

请查看http://git-scm.com/book/zh/v2/Git-内部交换协议了解如何通过某些传输协议执行此操作。请注意,这对于通过SSH进行的标准Git不起作用。

对于通过SSH进行的Git,最新版本的服务器端Git应该允许您直接从远程Git存储库中获取归档文件,然后将其传输到"tar t"中,以获取给定提交中所有文件的列表等信息。


14

GitHub 兼容 svn,因此您可以使用 svn ls 命令。

svn ls https://github.com/user/repository.git/branches/master/

BitBucket支持git存档,因此您可以下载tar存档并列出已存档的文件。这种方法效率不高,但是可行:

git archive --remote=git@bitbucket.org:repository HEAD directory | tar -t

12
不要将Git与GitHub混淆 :) - L.R.
它也感觉相当脆弱 - 在许多(约100个)存储库上运行时,我会从svn收到各种错误:“无法获取非目录条目”“500内部服务器错误”“没有更多凭据”。 - MichaelChirico
GitHub正在移除对Subversion的兼容性 - Martin Tournoij
GitHub正在移除对Subversion的兼容性 - undefined

9

当您要检出一个存储库时,您可以使用--no-checkout--depth 1跳过检出任何文件:

$ time git clone --no-checkout --depth 1 https://github.com/torvalds/linux .
Cloning into '.'...
remote: Enumerating objects: 75646, done.
remote: Counting objects: 100% (75646/75646), done.
remote: Compressing objects: 100% (71197/71197), done.
remote: Total 75646 (delta 6176), reused 22237 (delta 3672), pack-reused 0
Receiving objects: 100% (75646/75646), 201.46 MiB | 7.27 MiB/s, done.
Resolving deltas: 100% (6176/6176), done.

real    0m46.117s
user    0m13.412s
sys     0m19.641s

虽然只有一个.git目录:

$ ls -al
total 0
drwxr-xr-x   3 root  staff    96 Dec 26 23:57 .
drwxr-xr-x+ 71 root  staff  2272 Dec 27 00:03 ..
drwxr-xr-x  12 root  staff   384 Dec 26 23:58 .git

您可以通过以下方式获取目录列表:

$ git ls-tree --full-name --name-only -r HEAD | head
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Documentation/.gitignore
Documentation/ABI/README

或通过以下方式获取文件数:

$ git ls-tree -r HEAD | wc -l
   71259

或者通过以下方式获取文件总大小:

$ git ls-tree -l -r HEAD | awk '/^[^-]/ {s+=$4} END {print s}'
1006679487

2
这种技术有一个有趣的特点:git status 报告说仓库中的所有文件都已被删除。当使用 GUI 工具时,要注意它们可能会在大型仓库上暂时锁定! - Billy Jo

6

24
不要混淆Git和GitHub——我相信最初的问题是关于Git本身的。Git的安装/托管(GitHub / BitBucket / Stash)可能有多种浏览存储库的可能性。 - Krzysztof Wolny
好主意 @Anurag Kanungo 跳出思维定势 - Sentry.co

2

这种做法可能会被一些人认为是不好的,但对于github存储库来说,一个非常实用的解决方案就是编写一个脚本,例如“git-ls”:

#!/bin/sh
remote_url=${1:? "$0 requires URL as argument"}
curl -s $remote_url | grep js-directory-link | sed "s/.* title=\"\(.*\)\".*/\1/"

使其可执行并且可访问: chmod a+x git-ls; sudo cp git-ls /usr/local/bin。现在,您可以随意运行它:

git-ls https://github.com/mrquincle/aim-bzr
git-ls https://github.com/mrquincle/aim-bzr/tree/master/aim_modules

还要知道,有一个git instaweb实用程序可以用于本地文件。在我看来,拥有显示文件和像服务器一样的功能并不会破坏git固有的去中心化特性。


我用这个没有得到任何结果。curl似乎没有返回任何东西。 - Matthew Read
我现在肯定会推荐Anarug的API方法。虽然这种方法仍然有效:curl -s https://github.com/Itseez/opencv | grep js-directory-link | sed 's|.* title="\(.*\)".*|\1|' - Anne van Rossum
这个不起作用,curl 返回一个错误页面。 - Surya
这是近10年前的事情了。您将不得不自己检查HTML并类似地解析它。那里没有什么魔法。 - Anne van Rossum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接