git:是否将单个文件的内容发送到stdout?如rcs/cvs-p



BRIEF:git中将单个文件的内容发送到STDOUT的最佳方式是什么

例如RCS co -p的等价物;[P] 将检索到的修订打印在标准输出上,而不是存储在工作文件中。当co是管道的一部分时,此选项非常有用"--https://linux.die.net/man/1/co

例如。类似地CCD_ 2";将文件管道传输到标准输出">--https://linux.die.net/man/1/cvs">

例如,在git工作树/克隆中,相当于cvs co -p some-relative-pathname,我可以将其管道传输到其他命令中。

例如,相当于svn cat

例如hg cat [OPTION]... FILE...

我为什么要这么做

促使我写这篇文章的一个原因是,令人遗憾的是,我经常不得不处理UTF-16。XML和我的工具不太支持的其他格式(UNIXish、emacs、cygwin等)。我发现自己经常做一些事情,比如检查UTF-16,转换为UTF-8,编辑UTF-8,节省UTF-8,想要区分。。。导致临时文件的激增。而使用RCS/CVS合作程序,我可以编写更多的脚本。当然,我预计有人已经为git做了这件事,因此产生了这个问题。

实际上,我想要的不仅仅是发送到STDOUT,然后再发送到管道。我可能想做一些事情,比如输出到一个特定的修改过的文件名,等等。但如果你能做STDOUT,你可以写任何文件,而如果只能写入非stdout文件,当您可以然后提交STDOUT的cat时,你留下了一个烂摊子,你必须把它清理干净。另外,您不能执行-o tmp文件;cat tmp文件(如果您没有文件系统写入权限)。尽管直接写入文件的优点是可以保留文件属性,如权限和符号链接等特殊内容
理想情况下,两者都将内容输出到STDOUT以及输出到具有属性和内容的指定文件。

详细信息:

什么是最好的方式

通过";最佳方式";我指的是一种工作量最小的方式。理想情况下,只有一个命令行或管道(尽管如果不可能的话,显然会编写脚本)。

使简单的情况保持简单,但可以扩展到更复杂的情况。

理想情况下,不需要创建临时克隆或签出,然后丢弃它们。理想情况下,不要修改存储库或创建临时存储库/克隆。(信不信由你,至少有一个网页建议首先"将路径/to中的所有文件移动到存储库根目录,然后,删除除file.txt之外的所有文件!)

理想情况下,当chdir‘ed进入git工作树时,它会工作。在这种情况下,我只想指定一个存在于本地签出树中的文件路径名。相对于当前目录,相对于repo、子模块或超级项目的根稍次优。但是当然希望能够指定任何普通的git-tree ish。

XXX ./local-file相当于cvs co -p ./local-file

当然,当我实际上不在这样的存储库中,在远程环境中时,我希望能够做到这一点。但对于我目前的使用模式来说,这只是锦上添花。

理想情况下不需要git服务器在本地主机上侦听。。。有些系统并不认为这一定是安全的。。

最少可以输出单个文件的内容。如果它能有效地处理多个文件,则会获得加分,尽管这会引发如何做到这一点的问题:只需像cvs -p那样连接,丢失文件边界,或者发出有用的东西,如tar。

这是一个重复的问题吗

据我所知,这不是Q1的重复。如何从git存储库中稀疏地只签出一个文件?。

或者至少那个问答;线程会遇到很多困惑:例如,Q1的OP是否真的想进行签出、稀疏签出,或者他们只是想输出文件的内容。Q1让我在git archive上进行了一场有点疯狂的追逐。

Closer:Q2如何从Git中的特定修订版中检索单个文件?,到达git show objectgit show $REV:$FILE

尽管Q2的问题名称与我的非常接近,阅读的答案大多与第二季度的第一段有关

我有一个Git存储库,我想看看一些文件看起来如何几个月前。我在那个日期找到了修订本;它是27cf8e84bb88e24a4b3df2b77aab91a3735d8。我需要看看哪个文件看起来像,并将其另存为("新")文件。

所以他们没有提到最简单的事情相当于CCD_ 12-CCD_
如果Q2接受的答案提到了这一点,我会删除我的问题,但这看起来是一个重大变化。(如果我维护一个常见问题列表,我会这样做,但不确定这是否适合StackOverflow。)

也许git show HEAD:./file对我来说是显而易见的,但事实并非如此。

部分原因是git show HEAD:FILE---根目录与当前工作目录相对混乱。

也因为我在回答问题时提到了一些git-show gotchas,比如不存在的文件的静默错误以及符号链接的混淆行为。

这两者以及类似的问答;正如充满了误导性的大雁追逐。

例如,许多人建议使用git archive来做到这一点
在切换回git show之前,我一直在追求这只大雁
我认为标记目录然后提取单个文件可能效率低下。然而,我认为git archive的答案与cvs -p的答案基本相等是有用的。特别是因为这可能是提取多个文件或子树的最佳方式。

然而,最大的打击是每个人都提出让你眼睛流血的话题,而不是简单地使用HEAD或类似的方法。这些答案中的许多可能在一般情况下有效,在没有从工作树中提取单个文件的情况下,但对于我最感兴趣的一些简单的案例来说,这太过分了。我真正需要的是复习一下https://git-scm.com/docs/gitrevisions

  • 我很确定我过去知道这个问题的答案,但我并没有完全意识到,基本上,寻找新的线索会浪费很多时间,大雁追逐没有死胡同,等等

仅仅隐含正确的答案是不够的,但可能是模糊的,或者甚至是显式但隐藏的,使得标准搜索找不到它,或者在列表中找到很多其他偏离目标的答案。

在发布问题之前,我可能已经找到了答案

我努力为这个问题提供背景信息(以避免被指责自己没有试图弄清楚,主要是因为烦人的伪答案没有切中要害、不完整或完全错误),这让我最终找到了我认为的BKM:

cvs co -p0==cvs co -p some-relative-pathname

git show HEAD:./git-root-relative-pathname==cvs co -p ...,其中在CVS/RCS中获取这样一个相对于项目根的路径名需要更多的工作。

我将发布这个问题,并立即自己回答。

我认为,如果只是为了让其他人更容易快速找到答案,那么发布这篇文章是值得的。我没有很快找到它,尽管它的碎片散落在其他问答中;A螺纹。也要避免一些大雁追逐。

你称这次行动为什么

"提取"?

我的第一个想法是要求";如何从git中提取单个文件的内容;。但谷歌搜索发现许多帖子和网页";结账";或";"拉动";。

"提取文件标记";看起来很有希望,但点击通过https://gist.github.com/ssp/1663093#file-git提取文件降价标题是"如何从git存储库中提取具有其历史记录的单个文件;。而我试图做的是";提取一个没有历史记录的文件"好吧,至少该工具的作者只点击了一级洋葱皮就明确了这一点。

术语";提取物";导致混乱。

因此,我为这个问题提供的标题是:";将单个文件的内容发送到stdout";。用";类似于rcs/cvs-p〃;以进一步减少歧义。

亚达亚达。。。在当前工作树中,或从远程存储库中。。。当您只有一个相对于当前工作目录的文件路径名时,不一定是git-reo路由。。。亚达亚达。。。。

可能最接近的现有答案使用了单词";检索";一个单独的文件,我和谷歌都不认为它是等效的。大约一天后,我才找到答案,因为我几乎写完了所有这些。

在制品:清理-1个答案,因为没有更好的答案

一年多后:似乎没有人愿意为这个问题提供更好的答案,所以我会逐步清理它。大多数情况下,结合@torek的评论,试图让它们变得可理解,并提供一个快速紧凑的答案,不需要看很多手册并将其拼凑在一起。

(我不是在质疑-1的分数,我只是希望有人能提供一个干净的答案。"干净"并不意味着@torek提出的解决方案是不正确的,甚至不是关于错误代码等不雅之处,而是评论中的建议实际上是一个紧凑的答案。)

git cat-file -p <rev>:<cwd-or-root-relative-pathname>可能是答案

最简单的情况:CWD相对,如已检出

最接近cvs co -p <cwd-relative-pathname>

  • 似乎是git cat-file -p HEAD:./<cwd-relative-pathname>
  • 与竞争对手git show HEAD:./<cwd-relative-pathname>

在某些方面有所不同。

指定修订

CVS和GIT都可以通过许多不同的方式指定或请求修订。

CVS示例:数字版本号,如-r 1.2.3.4,或更人性化的-r named-tag,带有特殊标签,如HEAD和BASE。-D date

GIT有许多不同的方式来指定或请求修改。从相对用户友好的东西,如HEAD和HEAD^,到SHA-1 160位40十六进制数字哈希码,如d08c8b53975f513ad3b320bf55273b852f25247c,你可以用前几个十六进制数字缩写,中间有很多地方。

如果您说cvs co -p some-relative-pathname,则CVS默认为当前版本

GIT并没有以这种方式默认,因此通常需要显式地提供像HEAD:这样的GIT修订版或任何其他可能的格式。令人愉快的是,GIT允许像HEAD:这样的revspec通过冒号连接到路径名。如果您不指定类似HEAD的东西:您可能什么都得不到,没有输出,没有错误消息。

总结:

最接近cvs co -r CVS_REV -p <cwd-relative-pathname>

  • 似乎git cat-file -p GIT_REVSPEC:./<cwd-relative-pathname>
  • 类似于git show...

具有类似cvs co -D date...&lt--&gt。。。

CWD与repo ROOT相对路径名

在CVS中,cvs co -p a/b/c默认解释相对于当前工作目录CWD的路径。如果你想相对于";根";对于存储库,你必须做一些工作

在git中,git cat-file -p HEAD:a/b/c的解释不是相对于CWD,而是相对于存储库的根。

在git中,要指定相对于当前工作目录的位置,需要说./,例如git cat-file -p HEAD:./a/b/c。因此../也起作用。这是目前相当常见的惯例,尽管它会破坏任何脚本,这些脚本认为将./前置到任何不以/开头的路径名实际上都是NOP。

您可以通过类似git ls-files <cwd-relative-pathname>的方式获取GIT根的相对路径名。在CVS中。。。好吧,在CVS/RCS中,获得这样一个相对于项目根的路径名需要更多的工作。RCS实际上并不具有";项目根";并且依赖于围绕基本RCS的其他工具。即使使用CVS也可能发生这种情况,或者至少在人们仍在使用CVS的情况下会发生这种情况。

因此:

最接近cvs co -p <cwd-relative-pathname>

  • 似乎是git cat-file -p HEAD:./<cwd-relative-pathname>
  • 类似于git show...

最接近cvs co -p <root-relative-pathname>的东西

  • 似乎是git cat-file -p HEAD:<cwd-relative-pathname>
  • 类似于git show...

TBD:我可能会提供一些令人困惑的错误消息的例子,或者更糟的是,你没有得到错误消息或状态代码,但你仍然在做错误的事情。

TBD:例如,如果您意外地提供了GIT的绝对路径。

仅此而已

这就是我真正想要的。使用远程存储库的模块化扩展,修复git show格式等。然而,与其在这里结束答案,我希望它可能会帮助其他人看到我经历的一些死胡同——我需要在shell脚本和Makefile中小心使用这些东西。一些shell会话摘录,为了清晰起见进行了编辑。

遗留下来的旧东西需要清理

我还不想完全删除下面的内容,因为有些gotcha仍然相关。但我确实想重新制作

git show无声故障和其他意外

CCD_ 51=>无声错误

cwd1>git show README-->没有输出,甚至没有错误代码

这很令人失望,但我对git修订有足够的了解,可以尝试HEAD:README

cwd1>git show HEAD:README.Dragon_Stuff
致命:路径"some-dir/README"存在,但不存在"README">
提示:您的意思是"HEAD:some-dir/README"还是"HEAD:"/一些目录/自述文件'

这是一条有用的错误消息,甚至提供了一个错误代码:-)

cwd1>git show HEAD:./README.Dragon_Stuff

->耶!我得到输出

还不错。如果找不到对象,即可能会导致使用这个,但那个可以添加。

CCD_ 56=>更多无声的困惑

在另一个目录cwd2中,README是一个符号链接。

首先,通常:

$cwd2>git show README->无输出,无错误代码:-(
$cwd2>git show ./README->无输出,没有错误代码:–(

$cwd2>git show HEAD:./README某些目录/自述
-->嗯
哦,这是一个符号链接:/自述->一些目录/自述。Git show正在输出链接的目标。这很容易与文本文件的内容混淆。Q: 有没有办法减少这种混乱?

(顺便说一句,我在cygwin上做了这件事,它的符号链接处理很有趣。在Linux上可能会有所不同。我还没查。无论哪种情况都是不幸的。)

CCD_ 61=>更多无声的困惑

$cwd2>cd some-dir
$some-dir>git show README->没有输出,没有错误代码
$some-dir>CCD_ 64->无输出无错误代码

$some-dir>git show HEAD:README
某些目录/README
->嗯?

在本例中,cwd2恰好是存储库的根。

但是,即使cwd2不是repo根,也可能存在repo根/README这也可能是一个符号链接。我不知道指向某个目录/README还是其他目录/README会更令人困惑。

$some-dir>git show HEAD:./README
->耶!实际内容!

最新更新