【发布时间】:2017-09-13 19:00:12
【问题描述】:
为了明确这个问题,我不是在询问如何从历史记录中删除单个文件,例如这个问题:Completely remove file from all Git repository commit history。我也不是在询问来自 gitignore 的 untracking 文件,就像在这个问题中一样:Ignore files that have already been committed to a Git repository。
我说的是“更新 .gitignore 文件,然后从历史记录中删除与列表匹配的所有内容”,或多或少类似于这个问题:Ignore files that have already been committed to a Git repository。但是,不幸的是,该问题的答案不适用于此目的,因此我在这里尝试详细说明该问题,并希望找到一个不涉及人类查看整个源树以手动执行过滤器分支的好答案在每个匹配的文件上。
这里我提供一个测试脚本,目前正在执行Ignore files that have already been committed to a Git repository答案中的过程。它将在 PWD 下删除并创建一个文件夹root,所以在运行它之前要小心。我将在代码之后描述我的目标。
#!/bin/bash -e
TESTROOT=${PWD}
GREEN="\e[32m"
RESET="\e[39m"
rm -rf root
mkdir -v root
pushd root
mkdir -v repo
pushd repo
git init
touch a b c x
mkdir -v main
touch main/{a,x,y,z}
# Initial commit
git add .
git commit -m "Initial Commit"
echo -e "${GREEN}Contents of first commit${RESET}"
git ls-files | tee ../00-Initial.txt
# Add another commit just for demo
touch d e f y z main/{b,c}
## Make some other changes
echo "Test" | tee a | tee b | tee c | tee x | tee main/a > main/x
git add .
git commit -m "Some edits"
echo -e "${GREEN}Contents of second commit${RESET}"
git ls-files | tee ../01-Changed.txt
# Now I want to ignore all 'a' and 'b', and all 'main/x', but not 'main/b'
## Checkout the root commit
git checkout -b temp $(git rev-list HEAD | tail -1)
## Add .gitignores
echo "a" >> .gitignore
echo "b" >> .gitignore
echo "x" >> main/.gitignore
echo "!b" >> main/.gitignore
git add .
git commit --amend -m "Initial Commit (2)"
## --v Not sure if it is correct
git rebase --onto temp master
git checkout master
## --v Now, why should I delete this branch?
git branch -D temp
echo -e "${GREEN}Contents after rebase${RESET}"
git ls-files | tee ../02-Rebased.txt
# Supposingly, rewrite history
git filter-branch --tree-filter 'git clean -f -X' -- --all
echo -e "${GREEN}Contents after filter-branch${RESET}"
git ls-files | tee ../03-Rewritten.txt
echo "History of 'a'"
git log -p a
popd # repo
popd # root
此代码创建一个存储库、添加一些文件、进行一些编辑并执行清理过程。此外,还会生成一些日志文件。 理想情况下,我希望 a、b 和 main/x 从历史中消失,而 main/b 保留。然而,现在什么都没有从历史中删除。应该修改什么来实现这个目标?
如果这可以在多个分支上完成,则可以加分。但现在,将其保留在单个 master 分支中。
【问题讨论】: