简体   繁体   中英

How to NOT commit locally deleted files to git

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 local deletion (following this process) as something to be committed up to the repo, and we want that not to happen. Any ideas on how to commit only the additional files and never any deletions?

Use the Skip-Worktree Bit

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.

Listing Your Special Bits and Index-Only Files

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.

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

Just add images to gitignore. You do not need to store them in repo, right?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM