gpt4 book ai didi

git - 确定性追溯 .gitignore(如何让 Git 完全/追溯地忘记现在在 .gitignore 中的文件)

转载 作者:行者123 更新时间:2023-12-03 14:01:02 40 4
gpt4 key购买 nike

前言

这个问题试图消除关于应用 .gitignore 的困惑。追溯 ,不只是现在/ future .1

基本原理

我一直在寻找一种方法来追溯执行我当前的 .gitignore,好像我在第一次提交 中创建了 .gitignore .

我正在寻求的解决方案:

  • 不需要手动指定文件
  • 不需要提交
  • 将追溯适用于所有分支的所有提交
  • 将忽略工作目录中 .gitignore 指定的文件,不删除它们(就像最初由 root 提交的 .gitignore 文件一样)
  • 将使用 git,而不是 BFG
  • 将适用于 .gitignore 异常,例如:
  •  *.ext
    !*special.ext

    不是解决方案
    git rm --cached *.ext
    git commit

    这需要 1. 手动指定文件和 2. 额外的提交,这将导致在被其他开发人员 pull 时新忽略的文件删除。 (它实际上只是一个 git rm - 这是从 git 跟踪中删除 - 但它将文件单独留在本地(您的)工作目录中。其他 git pull 之后将收到文件删除提交)
    git filter-branch --index-filter 'git rm --cached *.ext'

    虽然这确实会追溯清除文件,但它 1. 需要手动指定文件和 2. deletes the specified files from the local working directory就像普通 git rm (对于其他 git pull 的人也是如此)!

    脚注

    1这里有很多关于 SO 的类似帖子,其中的问题定义不明确,甚至答案也不准确。见 this question with 23 answers accepted answer with ~4k votes不正确 根据“忘记”的标准定义 as noted by one mostly-correct answer , 和 only 2 answers包括 必填 git filter-branch命令。

    This question with 21 answers is 被标记为与前一个重复,但问题的定义不同(忽略与忘记),因此虽然答案可能是合适的,但它是 不是 重复。

    This question是我找到的最接近我正在寻找的东西,但答案并非在所有情况下都有效(带有空格的路径......),并且可能比创建外部存储库所需的复杂一些.gitignore 文件并将其复制到每个提交中。

    最佳答案

    编辑:我最近发现 git-filter-repo .这可能是一个更好的选择。调查 rationale 或许是个好主意和过滤器分支gotchas为你自己,但他们不会影响我下面的用例。

    这种方法使 Git 完全忘记忽略文件( 过去 /现在/ future ),但 不是 从工作目录中删除任何内容(即使从远程重新 pull 出)。
    此方法需要使用 /.git/info/exclude (首选)一个 预先存在的 .gitignore全部 具有要忽略/忘记的文件的提交。 1
    这个方法避免在下一个 git pull 上从其他开发人员机器中删除新忽略的文件2
    所有强制执行 Git 的方法都会忽略事后行为,从而有效地重写历史记录,因此具有 significant ramifications对于在此过程之后可能被提取的任何公共(public)/共享/协作存储库。 3
    一般建议:从一个干净的仓库开始 - 全部提交,工作目录或索引中没有任何待处理,并进行备份 !
    另外,评论/revision historythis answer (and revision historythis question )可能有用/有启发性。

    #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

    最后,关注 this GitHub guide 的其余部分(从第 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

    从现在修改的远程仓库中提取的其他开发人员应该进行备份,然后:
    #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

    脚注
    1 因为 /.git/info/exclude可以使用上面的说明应用于所有历史提交,也许是关于获取 .gitignore 的详细信息归档到需要它的历史提交中超出了此答案的范围。我想要一个合适的 .gitignore在根提交中,就好像这是我做的第一件事一样。其他人可能不在乎 /.git/info/exclude无论 .gitignore 在哪里,都可以完成同样的事情存在于提交历史中,显然重写历史是 非常敏感的话题,即使知道 ramifications .
    FWIW,可能的方法可能包括 git rebasegit filter-branch复制外部 .gitignore进入每个提交,例如 this question 的答案
    2 通过提交独立 git rm --cached 的结果来强制执行 git 忽略行为。命令可能导致新忽略的文件 删除 将来从强制推送的 Remote 中 pull 出。 --prune-empty git filter-branch 中的标志命令(或之后的 git reset HEAD^)通过自动删除先前的“删除所有忽略的文件”仅索引提交来避免此问题。
    3 重写 git 历史记录也会更改提交哈希,这将 wreak havoc关于公共(public)/共享/协作 repo 的 future pull 。请了解 ramifications在对这样的 repo 执行此操作之前,请充分考虑。 This GitHub guide指定以下内容:

    Tell your collaborators to rebase, not merge, any branches they created off of your old (tainted) repository history. One merge commit could reintroduce some or all of the tainted history that you just went to the trouble of purging.


    的替代解决方案不要影响远程仓库的是 git update-index --assume-unchanged </path/file>git update-index --skip-worktree <file> , 示例见 here .

    关于git - 确定性追溯 .gitignore(如何让 Git 完全/追溯地忘记现在在 .gitignore 中的文件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57418769/

    40 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com