-
Notifications
You must be signed in to change notification settings - Fork 32
/
git-remove.sh
executable file
·105 lines (94 loc) · 2.62 KB
/
git-remove.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/bin/bash
# Remove and purge old mistakes and/or unwanted big files from git history
# author: Iñaki Ucar <[email protected]>
# based on: http://blog.ostermiller.org/git-remove-from-history
if [ "$#" -ne 2 ]; then
echo "usage: $0 <repo-URL> <pattern>"
exit 1
fi
URL=$1
EXT=$2
confirm () {
read -r -p "${1:-Are you sure? [y/N]} " response
case $response in
[yY][eE][sS]|[yY])
true
;;
*)
false
;;
esac
}
clean () { rm -rf /tmp/workingrepo; }
# Create a clone of the repository
cd /tmp
git clone $URL workingrepo
if [ "$?" -ne 0 ]; then
echo ""
echo "ooops! something went wrong cloning the repo!"
clean
exit 2
fi
cd workingrepo
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
git branch --track ${branch##*/} $branch
done
# Find the files you want to remove
FILE_LIST=$(git rev-list master | \
while read rev; do
git ls-tree -lr $rev | cut -c54- | sed -r 's/^ +//g;'
done | sort -u | perl -e 'while (<>) {
chomp; @stuff=split("\t");$sums{$stuff[1]} += $stuff[0];
} print "$sums{$_} $_\n" for (keys %sums);' | \
sort -rn | grep $EXT)
echo ""
echo "You're going to remove the following files:"
echo ""
echo "$FILE_LIST"
echo ""
! confirm && clean && exit 0
FILE_LIST=$(echo "$FILE_LIST" | cut -d" " -f2)
echo ""
# Rewrite history and remove the old files
git filter-branch --tag-name-filter cat --index-filter \
"git rm -r --cached --ignore-unmatch ${FILE_LIST//$'\n'/ }" \
--prune-empty -f -- --all
# Prune all references with garbage collection and reclaim space
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --aggressive --prune=now
# Verify they have been removed
FILE_N=$(git rev-list master | \
while read rev; do
git ls-tree -lr $rev | cut -c54- | sed -r 's/^ +//g;'
done | sort -u | perl -e 'while (<>) {
chomp; @stuff=split("\t");$sums{$stuff[1]} += $stuff[0];
} print "$sums{$_} $_\n" for (keys %sums);' | \
sort -rn | grep $EXT | wc -l)
if [ "$FILE_N" -ne 0 ]; then
echo ""
echo "ooops! something went wrong removing the files!"
clean
exit 3
fi
# Push the history changes
echo ""
echo "Files successfully removed! Let's push the changes..."
echo ""
! confirm && exit 0
echo ""
git push origin --force --all
git push origin --force --tags
clean
# Done
echo ""
echo "Done! Now, you should tell your collaborators to rebase and prune their local copies with"
echo ""
echo " cd MY_LOCAL_GIT_REPO"
echo " git fetch origin"
echo " git rebase"
echo " git reflog expire --expire=now --all"
echo " git gc --aggressive --prune=now"
echo ""
echo "or to clone a fresh copy. And don't push that again! ;-)"
echo ""