Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
182 views
in Technique[技术] by (71.8m points)

Preserve git --assume-unchanged files between branch checkouts

I've been using git --assume-unchanged yacs/settings/development.py to ignore my local database configuration file in my dev branch. But when I want to switch branches (for deployments), I get an error that I still have changes pending:

% git checkout production
error: Your local changes to the following files would be overwritten by checkout:
    yacs/settings/development.py
Please, commit your changes or stash them before you can switch branches.
Aborting

Which is annoying. The only way I know how to get around this would be to stash it:

% git stash
% git checkout production
% git merge dev
% ./deploy.sh
% git checkout dev
% git stash pop
# On branch dev
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   yacs/settings/development.py
#

But now it's back in the index again (ugh)! Is there a better alternative to this workflow?

[I don't particularly care if the local changes stay locally (aka, it's ok if it's the production branch), I just don't want it pushed to a remote repository.]

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can try (git update-index man page):

git update-index --skip-worktree -- path

Skip-worktree bit can be defined in one (long) sentence: When reading an entry, if it is marked as skip-worktree, then Git pretends its working directory version is up to date and read the index version instead.

However, as mentioned in "git assume unchanged vs skip worktree":

Both options have problems. --assume-unchanged resets itself whenever the index gets discarded (e.g. git reset), so that will probably trip you up sooner or later. Same goes for --skip-worktree.


Plus, make sure to use Git 2.24 (Q4 2014).
Since 2012 (the OP's question), git stash has been ported to C (it is no longer a shell script) but it had (in its new implementation) to (re-)learn to write refreshed index back to disk.

See commit 34933d0 (11 Sep 2019) by Thomas Gummerer (tgummerer).
(Merged by Thomas Gummerer -- tgummerer -- in commit 34933d0, 20 Sep 2019)

stash: make sure to write refreshed cache

When converting stash into C, calls to 'git update-index --refresh' were replaced with the 'refresh_cache()' function.
That is fine as long as the index is only needed in-core, and not re-read from disk.

However in many cases we do actually need the refreshed index to be written to disk, for example 'merge_recursive_generic()' discards the in-core index before re-reading it from disk, and in the case of 'apply --quiet', the 'refresh_cache()' we currently have is pointless without writing the index to disk.

Always write the index after refreshing it to ensure there are no regressions in this compared to the scripted stash.
In the future we can consider avoiding the write where possible after making sure none of the subsequent calls actually need the refreshed cache, and it is not expected to be refreshed after stash exits or it is written somewhere else already.


Warning, that index might not be correctly rewritten when git stash is used with --quiet: With Git 2.25 (Q1 2020), Recent update to "git stash pop" made the command empty the index when run with the "--quiet" option, which has been corrected.

See commit df53c80 (13 Nov 2019) by Thomas Gummerer (tgummerer).
(Merged by Junio C Hamano -- gitster -- in commit 3c3e5d0, 01 Dec 2019)

stash: make sure we have a valid index before writing it

Reported-by: Grzegorz Rajchman
Signed-off-by: Thomas Gummerer

In 'do_apply_stash()' we refresh the index in the end.

Since 34933d0eff ("stash: make sure to write refreshed cache", 2019-09-11, Git v2.24.0-rc0 -- merge listed in batch #6), we also write that refreshed index when --quiet is given to 'git stash apply'.

However if '--index' is not given to 'git stash apply', we also discard the index in the else clause just before.

We need to do so because we use an external 'git update-index --add --stdin', which leads to an out of date in-core index.

Later we call 'refresh_and_write_cache', which now leads to writing the discarded index, which means we essentially write an empty index file.

This is obviously not correct, or the behaviour the user wanted.

We should not modify the users index without being asked to do so.

Make sure to re-read the index after discarding the current in-core index, to avoid dealing with outdated information.

Instead we could also drop the 'discard_cache()' + 'read_cache()', however that would make it easy to fall into the same trap as 34933d0eff did, so it's better to avoid that.

We can also drop the 'refresh_and_write_cache' completely in the quiet case.

Previously in legacy stash we relied on 'git status' to refresh the index after calling 'git read-tree' when '--index' was passed to 'git apply'.

However the 'reset_tree()' call that replaced 'git read-tree' always passes options that are equivalent to '-m', making the refresh of the index unnecessary.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...