【问题标题】:Git checkout using wildcard to a specific revisionGit 使用通配符签出特定版本
【发布时间】:2019-12-03 05:30:44
【问题描述】:

我在 Google 上搜索了 2 个小时,仍然找不到解决方案。

我想将所有带有通配符的文件签出到特定版本。我使用了以下命令:

git checkout 663090b1c 'src/app/**/*.spec.ts'

但它说:

error: pathspec 'src/app/**/*.spec.ts' did not match any file(s) known to git.

谁能帮帮我?

【问题讨论】:

  • 提交663090b1c 是否包含与src/app/app/**/*.spec.ts 路径规范匹配的任何文件? (尝试git ls-tree -r 663090b1c 并搜索名称以src/app/app/ 开头、包含任意数量的目录并以*.spec.ts 结尾的文件。)
  • @torek 抱歉,这是我的复制/粘贴问题。我已经更新了。
  • 啊,然后在git ls-tree -r 663090b1c 输出中搜索非重复的app/ 文件名。
  • 我试过你的命令,它显示了许多带有*.spec.ts的更改文件。
  • 好的,那么看来应该已经奏效了。 ... 有趣的是,我 可以 似乎在不同的存储库中重现了该问题。还不知道为什么(并且会离线一段时间,目前无法进一步调查)。

标签: git wildcard checkout revision


【解决方案1】:

我相信这应该可行,但显然不行。这是在 Documentation/**/*.txt 上使用最新的 Git(您可以在 https://github.com/git/git 获得)的效果。

我构建了 Git,然后使用系统 Git(在 2.21,略低于此版本 2.22.0.545.g9c9b961d7e)来执行此操作:

$ rm Documentation/*/*.txt
$ git status --short | head
 D Documentation/RelNotes/1.5.0.1.txt
 D Documentation/RelNotes/1.5.0.2.txt
 D Documentation/RelNotes/1.5.0.3.txt
 D Documentation/RelNotes/1.5.0.4.txt
 D Documentation/RelNotes/1.5.0.5.txt
 D Documentation/RelNotes/1.5.0.6.txt
 D Documentation/RelNotes/1.5.0.7.txt
 D Documentation/RelNotes/1.5.0.txt
 D Documentation/RelNotes/1.5.1.1.txt
 D Documentation/RelNotes/1.5.1.2.txt
$ git checkout -- 'Documentation/**/*.txt'
$ git status --short | head
$ 

然而现在:

$ ./git checkout HEAD -- 'Documentation/**/*.txt'
error: pathspec 'Documentation/**/*.txt' did not match any file(s) known to git

似乎路径规范在与索引一起使用时有效,但在与提交哈希一起使用时无效。

作为一种解决方法——请注意,这种解决方法有些缺陷,尽管您可以进一步修补它——您可以首先将所需的提交读入临时索引,然后从临时索引中执行git checkout。以下脚本完全未经测试。

#! /bin/sh
# git-co-c-ps: git checkout <commit> <pathspec>
# work around a bug in which combining <commit> and <pathspec> does not work
. git-sh-setup
case $# in
2) ;;
*) die "usage: $0 <commit> <pathspec>";;
esac

hash=$(git rev-parse "$1^{commit}") || exit 1
export GIT_INDEX_FILE=$(mktemp) || exit 1
rm -f $GIT_INDEX_FILE
trap "rm -f $GIT_INDEX_FILE" 0 1 2 3 15
git read-tree "$hash" || exit 1
git checkout -- "$2"

这里的(未经测试的)想法是将“$1”指定的提交读入临时索引。 (我们可以将^{commit} 放宽为^{tree},因为任何树形都应该足够了。)然后,将其读入临时索引后,我们使用“git checkout”模式和有效的路径规范($2) ,使用临时索引。这将写入工作树。

缺陷是现在更新的工作树文件在索引中也没有更新。真正的git checkout 会将这些相同的文件复制到索引中。应该可以取消设置$GIT_INDEX_FILEgit add 添加的文件到真实索引。这留作练习。请注意,它不像git add -- "$2" 那样简单,因为某些工作树文件可能在工作树中不是,因为它们是由git read-tree 操作读入临时索引的,而是因为他们已经在工作树中了。 (有些可能已被跟踪和修改但尚未暂存/添加,而另一些可能未被跟踪。)

另一个可能更好的解决方法是在临时索引上使用git ls-files 来查找感兴趣的文件。使用 xargs 或类似方法将这些文件名传递给在没有临时索引的情况下运行的 git checkout

files_file=$(mktemp)
trap "rm -f $files_file" 0 1 2 3 15
(
    export GIT_INDEX_FILE=$(mktemp) || exit 125
    rm -f $GIT_INDEX_FILE
    trap "rm -f $GIT_INDEX_FILE" 0 1 2 3 15
    git read-tree $hash
    git ls-files -z -- "$2"
) > $files_file
# if the inner shell exited with an error, exit now
case $? in 125) exit 1;; esac
xargs -0 ...

(填写其余部分以制作可用的 Git shell 命令也留作练习。)

【讨论】:

  • 注意:我在 git 日志中看到通配符与 pathspec 一起使用(自 Git 2.8 起):stackoverflow.com/a/35622183/6309。但它似乎确实不适用于 git checkout。
【解决方案2】:

先检查一个 find 命令会更容易:

find . src/app/**/*.spec.ts

查看列表是否正确。
作为一种解决方法,您可以这样做:

find . src/app/**/*.spec.ts | xargs git checkout <sha1> -- 
# or 
find . src/app/**/*.spec.ts -exec git checkout <sha1> -- {} \; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    相关资源
    最近更新 更多