使用Git

时间:2017-06-17 09:48:27

标签: git shell

我正在尝试检索修改/编辑我提供的文件列表的最新提交。

在实践中,如果我有a.txtb.txt,其中a.txt已于昨天修改且b.txt已在2小时前修改过,我想获得最新信息编辑b.txt

的提交

到目前为止,这是我的脚本:

for file in components/*/index.jsx
do
  # 1. Get the dirname of the current file
  dir=`dirname $file`
  # 2. Get a space separated list of files to check in $dir
  files=`find $dir -type f | grep -E -v "demo.jsx|.test.jsx|meta.json|__snapshots__" | tr '\n' ' '`
  # 3. Get the most recent commit that touched any of the listed files
  commit=`git log -n 1 --pretty=format:%H -- $files | cat`
  # 4. Get the version of the package.json at the specific $commit
  version=`git show $commit:packages/react-components/package.json | cat | grep -m 1 version`
  # 5. Insert the version in the meta.json of the component
  sed -i'' -e "2s/.*/$version/" $dir/meta.json
  # 6. Remove the backup file generated by sed
  rm $dir/meta.json-e
done

问题在于步骤#3,如果我提供多个文件,它根本不会返回任何提交。

这是有问题的步骤的日志:

❯ echo $files
components/Foobar/index.jsx components/Foobar/index.sss 

❯ git log -n 1 --pretty=format:%H -- $files | cat
# nothing

如果我跑了:

❯ git log -n 1 --pretty=format:%H -- components/Foobar/index.jsx components/Foobar/index.sss | cat
93012738e776f4ffe920161ba61501ed84b815a5

我得到了提交哈希......

想法?

更新: 如果我跑:

`echo "git log -n 1 --pretty=format:%H -- $files"`

它打印提交哈希,为什么?

2 个答案:

答案 0 :(得分:2)

这非常奇怪。以下是一些可以尝试的事情。

说明:

  • 在步骤3之前将脚本片段插入脚本并运行脚本,一次单独运行一个片段。
  • 复制并粘贴以避免拼写错误。
  • 为了防止for循环多次运行并产生大量输出,请暂时将components/*/index.jsx替换为components/Foobar/index.jsx(或者使用哪个文件触发问题)。
  • 不要在这些测试之间做任何事情(比如更改目录或运行git命令)。
  • 如果代码段没有产生预期的输出,请说出哪个片段以及输出是什么。
  • 不耐烦?尝试片段4(应该成功)和片段11(应该失败)。这表明这是正确的轨道,你应该尝试所有的步骤。

代码段:

  1. 检查哪个shell正在运行脚本

    echo "$SHELL"
    ls -l "$SHELL"
    

    预期输出:/bin/sh,可能是指向bashdash的符号链接。如果它是到另一个shell的符号链接(例如zsh),那将是一个问题,因为其他shell以不同的方式扩展变量。

  2. 仔细检查原始命令中"周围是否有引号($files)。

  3. 检查$IFS是否正确。

    echo -n "$IFS" | xxd -p
    

    预期输出:20090a<space><tab><newline>的十六进制) (我知道我已经要求你这样做了,但是请从脚本再次执行。)
    $IFS控制单词拆分,如果它是一个奇怪的值,会导致问题。

  4. 检查文件是否存在:

    ls components/Foobar/index.jsx components/Foobar/index.sss
    

    预期输出:ls应列出这两个文件 如果您收到“No such file or directory”错误,请检查该点脚本的工作目录以及签出的git分支。

  5. 尝试使用files变量,设置为字符串:

    files="components/Foobar/index.jsx components/Foobar/index.sss"
    ls $files
    

    预期输出:ls应列出两个文件。

    如果出现错误,例如

    ls: cannot access components/Foobar/index.jsx components/Foobar/index.sss: No such file or directory
    

    然后你的shell出了问题,因为它没有对未加引号的变量进行单词拆分。

  6. 尝试在反引号中运行ls

    files="components/Foobar/index.jsx components/Foobar/index.sss"
    output=`ls $files`
    echo "$output"
    

    预期输出:两个文件 如果你得到一个“没有这样的文件或目录”错误,那么你的shell就会被破坏,并且不会在反引号中正确地进行变量扩展。

  7. 使用find代替文字字符串:

    ls $files
    

    与代码段5不同,此代码段允许$files保留脚本中第2步的值。
    预期输出:ls应列出与前一个代码段相同的两个文件 如果您收到错误(没有此类文件或目录),则脚本的第2步出现问题。使用$files检查echo -n "$files" | od -c的值并发布。

  8. 使用文字文件参数尝试git命令:

    git log -n 1 --pretty=format:%H -- components/Foobar/index.jsx components/Foobar/index.sss | cat
    echo # output of previous command doesn't have a trailing newline
    

    预期输出:提交哈希。

  9. 尝试使用$files变量,设置为字符串:

    files="components/Foobar/index.jsx components/Foobar/index.sss"
    git log -n 1 --pretty=format:%H -- $files | cat
    echo # output of previous command doesn't have a trailing newline
    

    预期输出:提交哈希。

  10. 使用find代替文字字符串:

    git log -n 1 --pretty=format:%H -- $files | cat
    echo # output of previous command doesn't have a trailing newline
    

    预期输出:提交哈希。

  11. 尝试脚本中的原始命令:

    commit=`git log -n 1 --pretty=format:%H -- $files | cat`
    echo "$commit"
    

    预期输出:提交哈希。

答案 1 :(得分:1)

将此作为答案发布,但主要是解决方法:

for file in components/*/index.jsx
do
  dir=`dirname $file`
  files=`find $dir -type f | grep -E -v "demo.jsx|meta.json|.test.jsx|__snapshots__" | tr '\n' ' '`
  # We basically print the command as string, and evaluate it with backtricks
  # Use only if you have complete control over the project structure!
  commit=`$(echo git log -n 1 --pretty=format:%H -- $files) | cat`
  version=`git show $commit:packages/react-components/package.json | cat | grep -m 1 version`
  sed -i'' -e "2s/.*/$version/" $dir/meta.json
  rm $dir/meta.json-e
done

我不知道为什么需要它,但它似乎至少起作用。