Git - Difference Between 'assume-unchanged' and 'skip-worktree'

五迷三道 提交于 2019-11-25 21:46:16

问题


I have local changes to a file that I don\'t want to commit to my repository. It is a configuration file for building the application on a server, but I want to build locally with different settings. Naturally, the file always shows up when i do \'git status\' as something to be staged. I would like to hide this particular change and not commit it. I won\'t make any other changes to the file.

After some digging around, I see 2 options: \'assume-unchanged\' and \'skip-worktree\'. A previous question here talks about them but doesn\'t really explain their differences. My question is this: how are the two commands different? Why would someone use one or the other?


回答1:


You want skip-worktree.

assume-unchanged is designed for cases where it is expensive to check whether a group of files have been modified; when you set the bit, git (of course) assumes the files corresponding to that portion of the index have not been modified in the working copy. So it avoids a mess of stat calls. This bit is lost whenever the file's entry in the index changes (so, when the file is changed upstream).

skip-worktree is more than that: even where git knows that the file has been modified (or needs to be modified by a reset --hard or the like), it will pretend it has not been, using the version from the index instead. This persists until the index is discarded.

There is a good summary of the ramifications of this difference and the typical use cases here: http://fallengamer.livejournal.com/93321.html .

From that article:

  • --assume-unchanged assumes that a developer shouldn’t change a file. This flag is meant for improving performance for not-changing folders like SDKs.
  • --skip-worktree is useful when you instruct git not to touch a specific file ever because developers should change it. For example, if the main repository upstream hosts some production-ready configuration files and you don’t want to accidentally commit changes to those files, --skip-worktree is exactly what you want.



回答2:


Note: fallengamer did some tests in 2011 (so they may be outdated), and here are his findings:

Operations

  • File is changed both in local repository and upstream
    git pull:
    Git preserves local changes anyway.
    Thus you wouldn’t accidentally lose any data that you marked with any of the flags.
    • File with assume-unchanged flag: Git wouldn’t overwrite local file. Instead it would output conflicts and advices how to resolve them
    • File with skip-worktree flag: Git wouldn’t overwrite local file. Instead it would output conflicts and advices how to resolve them

  • File is changed both in local repository and upstream, trying to pull anyway
    git stash
    git pull
    Using skip-worktree results in some extra manual work but at least you wouldn’t lose any data if you had any local changes.
    • File with assume-unchanged flag: Discards all local changes without any possibility to restore them. The effect is like ‘git reset --hard’. ‘git pull’ call will succeed
    • File with skip-worktree flag: Stash wouldn’t work on skip-worktree files. ‘git pull’ will fail with the same error as above. Developer is forced to manually reset skip-worktree flag to be able to stash and complete the failing pull.

  • No local changes, upstream file changed
    git pull
    Both flags wouldn’t prevent you from getting upstream changes. Git detects that you broke assume-unchanged promise and choses to reflect the reality by resetting the flag.
    • File with assume-unchanged flag: Content is updated, flag is lost.
      git ls-files -v’ would show that flag is modified to H (from h).
    • File with skip-worktree flag: Content is updated, flag is preserved.
      git ls-files -v' would show the same S flag as before the pull.

  • With local file changed
    git reset --hard
    Git doesn’t touch skip-worktree file and reflects reality (the file promised to be unchanged actually was changed) for assume-unchanged file.
    • File with assume-unchanged flag: File content is reverted. Flag is reset to H (from h).
    • File with skip-worktree flag: File content is intact. Flag remains the same.

He adds the following analysis:

  • It looks like skip-worktree is trying very hard to preserve your local data. But it doesn’t prevent you to get upstream changes if it is safe. Plus git doesn’t reset the flag on pull.
    But ignoring the ‘reset --hard' command could become a nasty surprise for a developer.

  • Assume-unchanged flag could be lost on the pull operation and the local changes inside such files doesn’t seem to be important to git.

See:

  • Junio's (current git maintainer) comment regarding intent of assume-unchanged,

    In particular, Junio points out that changes to assume-unchanged files could accidentally be committed: "if Git can determine a path that is marked as assume-unchanged has changed without incurring extra lstat(2) cost, it reserves the right to report that the path has been modified (as a result, git commit -a is free to commit that change)."

  • difference between assume-unchanged and skip-worktree as discussed in git mailing list upon addition of skip-worktree patch.

He concludes:

Actually neither of the flags is intuitive enough.

  • assume-unchanged assumes that a developer shouldn’t change a file. If a file was changed – then that change is not important. This flag is meant for improving performance for not-changing folders like SDKs.
    But if the promise is broken and a file is actually changed, git reverts the flag to reflect the reality. Probably it’s ok to have some inconsistent flags in generally not-meant-to-be-changed folders.

  • On the other hand skip-worktree is useful when you instruct git not to touch a specific file ever. That is useful for an already tracked config file.
    Upstream main repository hosts some production-ready config but you would like to change some settings in the config to be able to do some local testing. And you don’t want to accidentally check the changes in such file to affect the production config. In that case skip-worktree makes perfect scene.



来源:https://stackoverflow.com/questions/13630849/git-difference-between-assume-unchanged-and-skip-worktree

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