Git 差异和复制

Git Diff and Copy

我想要 运行 针对作为 bitbucket 拉取请求的一部分添加或修改的文件的静态代码分析 (PMD) 报告。已修改的文件等在管道映像中本地可用,但是我需要做一个 git diff 来识别仅在源分支(从中提取)和目标分支(要合并到)之间的更改.然后,我将针对仅包含“已更改文件”的目录执行 PMD CLI(带有规则集等),以突出显示这些文件的任何问题,特别是作为更改的一部分。

我基本上想复制 git diff 结果中指示的文件。我希望这能提供更多背景信息。

我已经尝试找到一些示例并进行了测试,但是由于我对这些疯狂的 linux 命令缺乏理解,我只是没有做对:)

到目前为止我有以下命令,但结果是一个空文件夹。

git diff --name-only --pretty $BITBUCKET_PR_DESTINATION_BRANCH $BITBUCKET_BRANCH | xargs -i {} cp {} -t ~/branch-diff/

xargs 可能有一些文件的问题 - 参数太大。我提议类似

for name in $(git diff --name-only --pretty $BITBUCKET_PR_DESTINATION_BRANCH $BITBUCKET_BRANCH); do cp $name ~/branch-diff/; done

因此,您会将所有这些文件放在一个目录中(没有目录树)。另一个问题是它真的是你需要的。

首先,您当前解决方案存在的问题:

  1. xargs 不能很好地处理包含空格的文件名。你现在可能没有这个问题,你可以解决它,但最好尽可能避免这种情况。
  2. cp 不会构建目录树 - 您可以轻松验证 - 因此无论如何它都不会执行您的要求。
  3. git 不产生相对于当前路径的路径名,而是相对于工作树基的路径名。
  4. git diff $BITBUCKET_PR_DESTINATION_BRANCH $BITBUCKET_BRANCH 生成的文件名甚至不必存在于您的工作树中,而只存在于(至少一个)分支中。
  5. 如果一个文件的两个版本之间存在差异,您还没有说明要复制哪个版本!

使用标准文件工具的功能脚本类似于:

#!/bin/bash
# diffcopy.sh
#
DESTDIR=""
BRANCH1=""
BRANCH2=""

# so relative paths match git output
SRCDIR="$(git rev-parse --show-toplevel)"

# choose the branch whose files we want to copy
git checkout "$BRANCH2"

# make the output directory
mkdir -p "$DESTDIR"

# sync the changed files
rsync -a --files-from=<(git diff --name-only "${BRANCH1}".."${BRANCH2}") "$SRCDIR" "$DESTDIR"

# restore working copy
git checkout -

纯粹在git中可能是更好的方法,但我不知道。

如果你有 cpxargs 的 GNU 变体,你可以这样做:

git diff --name-only -z $BITBUCKET_PR_DESTINATION_BRANCH $BITBUCKET_BRANCH |
   xargs -0 cp --target-directory="$HOME/branch-diff/" --parents

这不会为每个文件生成 cp,而是使用一个 cp 过程复制尽可能多的文件。通过指定 --target-directory,目标可以在 cp 命令中排在第一位,并且 xargs 可以根据需要在 cp 命令的和处粘贴任意多个源文件名。 --parents 保留源文件的目录名称。

git diff中的-z用NUL字符分隔文件名而不是换行符,xargs-0知道如何取NUL分隔的路径分开列出而不会绊倒文件名中的空白字符。