We have a situation where were are using git to stash myriad scans (images) and do not wish to preserve them on the local machine once set on up; however, git is seeing each loc
The git-update-index(1) command provides some ways of dealing with this. Based on the assumption that you want to keep the blobs in your history while deleting them from your working tree, you could use the following:
git add --all
git commit --message="Add new assets to repository."
git update-index update-index --skip-worktree <files ...>
rm <files ...>
Note that the last line isn't a Git command because you're removing the files from the working tree in the shell after you've stored them in the index. Don't use git rm
by mistake, because it operates on the index.
To see the files you've marked with the skip-worktree bit:
git ls-files -v | awk -v IGNORECASE=1 '$1 ~ /s/ {print}'
You can also use git-ls-files(1) to find files in the index that have been removed from your working tree.
Just add images to gitignore. You do not need to store them in repo, right?
For each file to be deleted, do this:
git update-index --assume-unchanged <file>
This should stop Git from asking you to commit the deletion.
That being said, perhaps a better solution would be to use SFTP with permissions set to disallow deleting or modifying files once uploaded.
(edit: package up the payload as a self-contained script)
You're after a nearly status-only local repository that tracks the existence of everything you've ever created but keeps the contents of only the most recent stuff (after pushing everything upstream). Presuming you never reuse a pathname, here's the ritual:
One-time setup:
Create and push an everything
branch that tracks every image you've got so far. Base a (local-only) worktree
branch off that.
git checkout -b everything # this will be the branch you push
git push origin everything # .
git checkout -b worktree # you'll stay on this branch
Work (almost) as if you didn't want to do anything special:
Everything that needs preserving upstream is on the everything
branch, and you've got worktree
checked out. Remove images you're done with from the worktree, make new images there that need pushing, and commit the new worktree state:
# work work:
rm -r anything/ you\'re/ done with
create new images
git add -A . # good gitignore patterns make life easy
git commit
To do the requested work, run
merge-push-and-cleanup # the script below
After which everything's stored upstream, nothing redundant remains locally, and you're ready for more work.
The merge-push-and-cleanup
script:
#!/bin/sh
# Git can do "index-only" merges when the content doesn't need to be examined,
# you can casually create sideband indexes, and `git commit-tree` works on any
# tree in the repo.
(
# ^ subshell to keep G_I_F export local
export GIT_INDEX_FILE=.git/sideband-index
# make a merged index that includes everything from both branches, by
# starting from an empty merge base so all files show up as additions.
git read-tree -im $(git mktree </dev/null) worktree everything
# commit to the `everything` branch straight from the constructed index,
# reusing the commit message from `worktree`
git cat-file -p worktree | sed 1,/^$/d \
| git commit-tree -p everything -p worktree $(git write-tree --missing-ok) \
| xargs git update-ref refs/heads/everything
)
git push origin everything
# preserve the branch metadata and, just for safety, your latest images
# by packing it all up:
mkdir -p .git/preserved/pack
rm -f .git/preserved/pack/*
(
git rev-list worktree everything
git rev-parse worktree^{tree} everything^{tree}
git ls-tree -rt worktree | awk '{ print $3 }'
git ls-tree -rt everything | awk '$2 != "blob" { print $3 }'
) \
| git pack-objects .git/preserved/pack/pack
# now for the fun one:
rm -rf .git/objects/* # !!!
# put the preserved stuff back:
mv .git/preserved/pack .git/objects