如何在git diff --no-index命令中忽略目录?

14

我正在尝试在同一代码库中创建两个文件夹之间的彩色差异(这可能是完全错误的方法)。

我相信其中一种实现方式是通过 git diff --no-index folder1 folder2,它会自动为您创建一个补丁(很酷)。

但是,该差异还包括(正如人们所期望的)所有被.gitignore忽略的文件。

folder1
  node_modules
  src/
  .gitignore
  package.json
  README.md

folder2
  node_modules
  src/
  .gitignore
  package.json
  README.md

我想忽略 node_modules

还有哪些可能性?替代方案?


1
你找到了有效的解决方案吗?我有一个相关的难题。 - Michael
以下是在bash中尝试使用.gitignore文件从folder1过滤出不需要的路径的方法:src=folder1 dst=folder2; { { git diff --no-index --no-renames --name-only -- "$src" "$dst" | sed '/^\/dev\/null$/d;s~^[^/]*/~~;/^[^/]*\.git\//d' | sort -u | tee /dev/stderr; } | git -C "$src" check-ignore --stdin; } |& uniq -u | while read file; do f1="$src/$file" f2="$dst/$file"; git diff --no-index --no-renames -- "$([ -e "$f1" ] && echo "$f1" || echo /dev/null)" "$([ -e "$f2" ] && echo "$f2" || echo /dev/null)"; done - Jay
4个回答

1

简化版:

git diff $(git commit-tree -m '' @:folder1) $(git commit-tree -m '' @:folder2)

该操作会对每个树进行即时提交(与检出时的树相同),并对这两个提交进行差异比较。

如果您想对当前工作目录内容进行此操作,则可以轻松创建草稿提交。

( export GIT_INDEX_FILE=.git/scratch-index
  git add .
  temp=`git write-tree`
  git diff $(git commit-tree -m '' $temp:folder1) $(git commit-tree -m '' $temp:folder2)
)

如果您需要更精细的控制,您可以使用管道git ls-files并使用任何路径规范将其输入到git update-index --add --stdin中。


0
如果您关心比较目录的两个“已版本化”的内容(例如:在当前提交中dir1/dir2/的内容,而不考虑索引或工作树中可能存在的任何修改),您可以要求git diff比较已经写入存储库的两个“树”:
# 'HEAD:dir1' is a syntax to designate the tree object stored at path 'dir1'
# in the current active commit ('HEAD')
git diff HEAD:dir1 HEAD:dir2

这将仅比较 Git 跟踪的内容(因此:不写入存储库的 .gitignore 内容将不会显示)


如果您想比较索引或工作树中的修改,同时又要遵守 .gitignore 规则,可以使用一些技巧让 git 创建该树:

  • 如果您想比较暂存区内容:

git write-tree 将从暂存区内容创建一个树对象。

treehash=$(git write-tree)
git diff ${treehash}:dir1/ ${treehash}:dir2/
  • 如果你想比较已跟踪文件的工作树内容:

你可以使用 git stash create 快速创建一个包含该内容的树

hash=$(git stash create)
git diff ${hash}:dir1/ ${hash}:dir2/

请注意,git stash *create*git stashgit stash push不同,它创建了在存储中保存的结构,但不会将其更新到存储区。

0

您可以尝试使用assume-unchanged标志
https://git-scm.com/docs/git-update-index

--[no-]assume-unchanged

当指定此标志时,不会更新路径记录的对象名称。
相反,此选项为路径设置/取消设置“假定未更改”位。

当“假定未更改”位打开时,用户承诺不更改文件,并允许Git假定工作树文件与索引中记录的内容相匹配。如果要更改工作树文件,则需要取消设置该位以告知Git。在使用具有非常缓慢的lstat(2)系统调用(例如cifs)的文件系统上处理大型项目时,这有时很有帮助。

如果Git需要修改索引中的此文件(例如在合并提交时),则Git将失败(优雅地);因此,在上游更改了假定未跟踪的文件的情况下,您需要手动处理该情况。

enter image description here


2
我不太明白这个如何与diff结合使用或替换它。 - chemoish
使用此标志将文件设置为 .gitignore 内的文件。 - CodeWizard
致命错误:无法标记文件...(尝试执行 git update-index --[no-]assume-unchanged node_modules 时) - chemoish

0

我没有一个像人们希望的那样简单的解决方案,但有两个有点不寻常但容易实现的替代方案。

  1. 如果你可以不用被忽略的文件,只需在执行差异之前从仓库中清除它们:
# -x means that files from the .gitignore will also be cleaned
# --interactive shows you what will be deleted before doing so
git clean -x --interactive folder1 folder2

# now the files simply don't exist any more
git diff --no-index folder1 folder2

另一种在无需永久删除被忽略文件的情况下实现这一点的方法是快速在本地克隆仓库:
cd ..
git clone original-directory clone-of-repo

cd clone-of-repo
# in the clone, ignored files are naturally not included
git diff --no-index folder1 folder2

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