无法使用 bash 脚本从 git 历史记录中删除文件
Unable to use bash script to remove files from git history
我正在编写的 bash 脚本有问题。我正在尝试应用 this procedure from Github documentation 的第 3 步从我们的 git 历史记录中删除我们存储库历史记录中的所有文件。例如,如果 .gitignore 忽略 .txt,我想从历史记录中删除所有 .txt。依此类推。git忽略行。
我可以在示例文件中使用通配符。所以我可以运行以下删除所有.txt文件:
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.txt' --prune-empty --tag-name-filter cat -- --all
所以我试着制作一个 bash 脚本来做同样的事情。
我制作了一个简单的 .gitignore 文件来测试它,如下所示:
#foo
*.txt
*.docx
我的 shell 脚本如下所示:
#!/bin/bash
s1="#"
str1="'git rm --cached --ignore-unmatch "
str2="'"
cat .gitignore | while read line
do
if [[ $line == *"$s1"* ]]
then
echo #skip
else
str3=$str1$line$str2
git filter-branch --force --index-filter $str3 --prune-empty --tag-name-filter cat -- --all
fi
done
但是,这会导致以下输出:
fatal: bad revision 'rm'
fatal: bad revision 'rm'
(.git忽略文件的每一行一次)
我做错了什么?
我相信这可能会满足您的要求。
#!/bin/bash
cat .gitignore | while read line
do
if [[ $line == *#* ]]
then
echo #skip
else
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch '"$line" --prune-empty --tag-name-filter cat -- --all
fi
done
我避免了所有只会使事情复杂化的无意义的中间变量。 (虽然只是从 str1
中删除单引号并删除 str2
可能就足够了,但就我而言,这是更明智的。)
过滤器只需要是单个字符串,但如何构建该字符串取决于您。
您可能还可以从 gitignore 收集所有模式,并且只需 运行 filter-branch 一次(那时不需要 --force
)。
#!/bin/bash
patts=()
while read -r line
do
if [[ $line != *#* ]]; then
patts+=("$line")
fi
done < .gitignore
git filter-branch --index-filter 'git rm --cached --ignore-unmatch '"${patts[*]}" --prune-empty --tag-name-filter cat -- --all
另请注意,您可能应该确定您在这里只处理简单的模式,因为 rm
和 .gitignore
对模式的理解在我不了解的所有情况下都不完全相同没想到。
我正在编写的 bash 脚本有问题。我正在尝试应用 this procedure from Github documentation 的第 3 步从我们的 git 历史记录中删除我们存储库历史记录中的所有文件。例如,如果 .gitignore 忽略 .txt,我想从历史记录中删除所有 .txt。依此类推。git忽略行。
我可以在示例文件中使用通配符。所以我可以运行以下删除所有.txt文件:
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.txt' --prune-empty --tag-name-filter cat -- --all
所以我试着制作一个 bash 脚本来做同样的事情。
我制作了一个简单的 .gitignore 文件来测试它,如下所示:
#foo
*.txt
*.docx
我的 shell 脚本如下所示:
#!/bin/bash
s1="#"
str1="'git rm --cached --ignore-unmatch "
str2="'"
cat .gitignore | while read line
do
if [[ $line == *"$s1"* ]]
then
echo #skip
else
str3=$str1$line$str2
git filter-branch --force --index-filter $str3 --prune-empty --tag-name-filter cat -- --all
fi
done
但是,这会导致以下输出:
fatal: bad revision 'rm'
fatal: bad revision 'rm'
(.git忽略文件的每一行一次)
我做错了什么?
我相信这可能会满足您的要求。
#!/bin/bash
cat .gitignore | while read line
do
if [[ $line == *#* ]]
then
echo #skip
else
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch '"$line" --prune-empty --tag-name-filter cat -- --all
fi
done
我避免了所有只会使事情复杂化的无意义的中间变量。 (虽然只是从 str1
中删除单引号并删除 str2
可能就足够了,但就我而言,这是更明智的。)
过滤器只需要是单个字符串,但如何构建该字符串取决于您。
您可能还可以从 gitignore 收集所有模式,并且只需 运行 filter-branch 一次(那时不需要 --force
)。
#!/bin/bash
patts=()
while read -r line
do
if [[ $line != *#* ]]; then
patts+=("$line")
fi
done < .gitignore
git filter-branch --index-filter 'git rm --cached --ignore-unmatch '"${patts[*]}" --prune-empty --tag-name-filter cat -- --all
另请注意,您可能应该确定您在这里只处理简单的模式,因为 rm
和 .gitignore
对模式的理解在我不了解的所有情况下都不完全相同没想到。