I have an update to the answer from @phd on how to do this. Thought I'd share since it took me hours of troubleshooting to do what I was trying to accomplish and it could be helpful to other people that come across this.
I had a situation where I needed to delete a LOT of previously tracked files from the remote repo but wanted to keep those files locally for any developers that had already checked out the version of the repo where those files were tracked. What made this worse is that these files were in multiple directories, subdirectories and a few individual files in the root directory.
The main issue was that the commit where the files were deleted was NOT the last commit made to the repo. It was a few commits back.
This solution lets you use any commit to do the same thing so you aren't just limited to the last commit. This answer combines a some blog posts and other Stackoverflow answers
- Pull from the latest version of the branch (e.g.
git pull origin master
)
- Git checkout the commit right before all of the files were removed from git (e.g.
commit_hash_right_before_files_were_deleted
)
- Get the difference between the list of files in the current commit vs the list of files that were deleted in the commit where all the files were deleted (e.g
git log --diff-filter D --pretty="oneline" --name-only --format= -l 0 commit_hash_right_before_files_were_deleted..commit_hash_where_where_files_were_deleted
)
- Convert that list into the
sed
command to remove empty lines (e.g. sed '/^$/d'
Got that from here: https://waylonwalker.com/git-find-deleted-files/#git-reflog-diff-filter)
- Pipe that list to the Zip command to zip all of those deleted files up into zip file (e.g.
sed '/^$/d' | zip deleted-files.zip -@
. The sed
command removes blank empty lines from the output. Got that from here https://superuser.com/a/1228717/1247351 )
- Switch back to the branch (e.g.
git checkout master
)
- Unzip the deleted files zip file (e.g.
unzip deleted-files.zip
)
- Reset the list of files to remove it from the local index to avoid committing them.
Full code:
git pull origin master
git checkout commit_hash_right_before_files_were_deleted
git log --diff-filter D --pretty="oneline" --name-only --format= -l 0 commit_hash_right_before_files_were_deleted..commit_hash_where_files_were_deleted | sed '/^$/d' | zip deleted-files.zip -@
git checkout master
unzip deleted-files.zip
git reset -- `git diff --diff-filter=D --name-only commit_hash_where_files_were_deleted`
There are some additional arguments that we are passing to the git log
command . We are passing the -l 0
argument to avoid git log from truncating the list of returned changed files. We are also passing the --format=
argument to prevent git log from outputting the commit hash and the commit message; we only care about the list of changed files.
Tried a few solutions including trying to to the git update-index --assume-unchanged
command but when I tried to pull from the remote branch, it would just keep deleting the files. This is best solution that met my needs.