Git checkout to external work tree and remove deleted files

时光怂恿深爱的人放手 提交于 2020-01-02 05:27:13

问题


We want to use Git to deploy code on our webserver. Therefore, we have a initialized a bare repository on our production server. Whenever we release a new version, we perform a git checkout into the DocumentRoot of the website:

git --work-tree=/path/to/webroot/ checkout -f master

In the subdirectories of webroot, there are several files which are not tracked by Git (Cache files, user-uploaded files etc.). These must of course not be deleted by Git when performing the checkout (and this part works fine so far).

However, Git also does not delete files which were previously tracked, but have been removed in the meantime (e.g. they were deleted in the development process because they are no longer needed). Such files currently survive the checkout process, leading to a steadily increasing number of "dead" files. Is there a way to make Git delete such files when performing the checkout?

EDIT - steps to reproduce:

# create dirs and repos
cd /base/path
mkdir repo.git
mkdir target
cd repo.git && git init

# create, add and commit two files
touch test1.txt
touch test2.txt
git add test1.txt test2.txt
git commit -m testcommit

# checkout to target directory
git --work-tree=../target checkout master -f
# target directory now contains both files

# remove one file from file system and git repo, commit
rm test2.txt
git rm test2.txt
git commit -m deletecommit

# checkout to target again
git --work-tree=../target checkout master -f
# target still contains both files

回答1:


By using one working directory for some of the work and then another for the rest you are getting them out of sync with the rest of the repository. Git does not seem to be intended to be used that way.

If you want to use multiple working directories with one git repository there are some solutions available. See the stackoverflow question here.

Otherwise you can either:

  • Clone the repository directly into the webroot. Though that would imply starting a fresh webroot.
  • Clone a copy for but not in webroot and stick to consistently using it with the webroot as its only working directory (once you've got it in-sync with what you already have there). You can use git config core.worktree ../target to set it as the repositories default.



回答2:


However, Git also does not delete files which were previously tracked, but have been removed in the meantime

Yes, with Git 2.22 (Q2 2019) and git checkout --overlay, it does.
"git checkout --no-overlay" can be used to trigger a new mode of checking out paths out of the tree-ish, that allows paths that match the pathspec that are in the current index and working tree and are not in the tree-ish.

See commit e92aa0e (04 Feb 2019), commit 1495ff7, commit 091e04b (08 Jan 2019), and commit b7033e7, commit 5160fa0, commit 6fdc205, commit 536ec18, commit b702dd1, commit a0cc584 (20 Dec 2018) by Thomas Gummerer (tgummerer).
Suggested-by: Jonathan Nieder (artagnon).
(Merged by Junio C Hamano -- gitster -- in commit 7d0c1f4, 07 Mar 2019)

checkout: introduce --{,no-}overlay option

Currently 'git checkout' is defined as an overlay operation, which means that if in 'git checkout <tree-ish> -- [<pathspec>]' we have an entry in the index that matches <pathspec>, but that doesn't exist in <tree-ish>, that entry will not be removed from the index or the working tree.

Introduce a new --{,no-}overlay option, which allows using 'git checkout' in non-overlay mode, thus removing files from the working tree if they do not exist in <tree-ish> but match <pathspec>.

Note that 'git checkout -p <tree-ish> -- [<pathspec>]' already works this way, so no changes are needed for the patch mode.
We disallow 'git checkout --overlay -p' to avoid confusing users who would expect to be able to force overlay mode in 'git checkout -p' this way.

Untracked files are not affected by this change, so 'git checkout --no-overlay HEAD -- untracked' will not remove untracked from the working tree.
This is so e.g. 'git checkout --no-overlay HEAD -- dir/' doesn't delete all untracked files in dir/, but rather just resets the state of files that are known to git.

And you have a new git config setting:

checkout.overlayMode:

In the default overlay mode, git checkout never removes files from the index or the working tree.
When setting checkout.overlayMode to false, files that appear in the index and working tree, but not in <tree-ish> are removed, to make them match <tree-ish> exactly.




回答3:


I have used git-clean to do something similar. If the files you don't want to remove are in gitignore, you can delete all unwanted files.



来源:https://stackoverflow.com/questions/31076608/git-checkout-to-external-work-tree-and-remove-deleted-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!