这个问题试图消除关于追溯应用 .gitignore 的混淆,而不仅仅是现在/未来。1
我一直在寻找一种方法来追溯强制执行我当前的 .gitignore ,就像我在第一次提交中创建了 .gitignore 一样。
我正在寻求的解决方案:
*.ext
!*special.ext
Run Code Online (Sandbox Code Playgroud)
git rm --cached *.ext
git commit
Run Code Online (Sandbox Code Playgroud)
这需要 1. 手动指定文件和 2. 附加提交,这将导致在其他开发人员拉取时删除新忽略的文件。(它实际上只是一个git rm
- 这是从 git 跟踪中删除- 但它会将文件单独留在本地(您的)工作目录中。 之后其他人git pull
将收到文件删除提交)
git filter-branch --index-filter 'git rm --cached *.ext'
Run Code Online (Sandbox Code Playgroud)
虽然这确实可以追溯清除文件,但它 1. 需要手动指定文件和 2.从本地工作目录中删除指定的文件,就像普通的一样git rm
(对于其他人也是如此git pull
)!
1这里有很多关于 SO 的类似帖子,其中包含不那么明确定义的问题,甚至更不准确的答案。请参阅带有 23 个答案的此问题,其中根据“忘记”的标准定义(如一个基本正确的答案所述),其中约 4k 票的接受答案是不正确的,并且只有2 个答案包含所需的 git filter-branch
命令。
这21分问题的答案 是标记为前一个的副本,但问题是有不同的定义(忽略VS忘了),因此,尽管答案可能是适当的,它是不重复的。
这个问题是我发现的最接近我正在寻找的问题,但答案并不适用于所有情况(带空格的路径......),并且在创建外部到-repository .gitignore 文件并将其复制到每个提交中。
goo*_*ogy 10
编辑:我最近发现了git-filter-repo。可能是更好的选择。也许是个好主意,调查理由和过滤分支陷阱的自己,但他们也不会影响到我下面的用例。
这种方法使混帐完全忘记或忽略的文件(过去/现在/未来),但并没有从工作目录(远程即使再拉)删除任何东西。
此方法需要在所有具有要忽略/忘记的文件的提交中使用/.git/info/exclude
(preferred) OR a pre-existing 。1.gitignore
这种方法避免了在接下来的2 个开发者机器上删除新忽略的文件git pull
所有强制执行 Git 的方法都会忽略事后行为,有效地重写历史记录,因此对在此过程之后可能被拉出的任何公共/共享/协作存储库产生重大影响。3
一般建议:从一个干净的 repo 开始- 提交的所有内容,工作目录或索引中没有任何未决的内容,并进行备份!
此外,评论/修订历史的这个答案(和修订历史的这个问题)可能是有用/启发。
#commit up-to-date .gitignore (if not already existing)
#these commands must be run on each branch
#these commands are not strictly necessary if you don't want/need a .gitignore file. .git/info/exclude can be used instead
git add .gitignore
git commit -m "Create .gitignore"
#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
#if using .git/info/exclude, it will need to be modified per branch run, if the branches have differing (per-branch) .gitignore requirements.
git ls-files -z --ignored --exclude-standard | xargs -r0 git rm --cached
#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.
git commit -m "ignored index"
#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits. If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command
git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -r0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all
#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch
git ls-files --other --ignored --exclude-standard
Run Code Online (Sandbox Code Playgroud)
最后,遵循本 GitHub 指南的其余部分(从第 6 步开始),其中包括有关以下命令的重要警告/信息。
git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
Run Code Online (Sandbox Code Playgroud)
从现在修改的远程存储库中提取的其他开发人员应该进行备份,然后:
#fetch modified remote
git fetch --all
#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed
git reset FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)
1因为/.git/info/exclude
可以使用上述说明应用于所有历史提交,所以有关将.gitignore
文件放入需要它的历史提交的详细信息可能超出了本答案的范围。我希望.gitignore
在根提交中有一个适当的,好像这是我做的第一件事。其他人可能不在乎,因为/.git/info/exclude
无论.gitignore
提交历史记录存在于何处都可以完成相同的事情,并且显然重写历史记录是一个非常敏感的主题,即使知道后果也是如此。
FWIW,潜在的方法可能包括git rebase
或git filter-branch
将外部 复制.gitignore
到每个提交中,就像这个问题的答案
2通过提交独立git rm --cached
命令的结果在事后强制执行 git ignore 行为可能会导致在未来从强制推送的远程拉取中删除新忽略的文件。命令(或之后)中的--prune-empty
标志通过自动删除先前的“删除所有忽略的文件”索引仅提交来避免此问题。git filter-branch
git reset HEAD^
3重写 git 历史也会改变提交哈希,这将对未来从公共/共享/协作存储库中拉取造成严重破坏。在对这样的 repo 执行此操作之前,请完全了解后果。本 GitHub 指南指定了以下内容:
告诉你的合作者底垫中,不合并,他们创造了旧的(污点)仓库的历史掉任何分支机构。一次合并提交可能会重新引入您刚刚遇到清除问题的部分或全部受污染历史记录。
不影响远程存储库的替代解决方案是git update-index --assume-unchanged </path/file>
或git update-index --skip-worktree <file>
,其示例可在此处找到。
小智 6
这可能只是部分答案,但以下是我如何根据当前的 .gitignore 文件追溯删除以前的 git 提交中的文件:
copy .gitignore ..\
并仅将临时副本复制到目录级别nbproject/Makefile-*
),您需要编辑临时复制的 .gitignore 文件,以便读取这些行glob:nbproject/Makefile-*
git filter-repo --invert-paths --paths-from-file ..\.gitignore
。我的理解是,这使用临时副本作为要删除的文件/目录列表。注意:如果您收到有关您的存储库不是干净克隆的错误,请在 git-filter-repo 帮助中搜索“FRESH CLONE SAFETY CHECK AND --FORCE”。当心。有关更多信息,请参阅: git-filter-repo 帮助(搜索“基于多个路径的过滤”)
免责声明:我不知道我在做什么,但这对我有用。
归档时间: |
|
查看次数: |
3439 次 |
最近记录: |