git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/2] Add --no-filters option to git-add

From
Andrej Shadura via GitGitGadget <gitgitgadget@gmail.com>
Date
Feb 20, 2021, 17:07 UTC
Message-ID
<pull.880.v2.git.1613840865.gitgitgadget@gmail.com>
In-Reply-To
<pull.880.git.1613758333.gitgitgadget@gmail.com>

It is possible for a user to disable attribute-based filtering when committing by doing one of the following:

 * Create .git/info/attributes unapplying all possible transforming
   attributes.
 * Use git hash-object and git update-index to stage files manually.

Doing the former requires keeping an up-to-date list of all attributes which can transform files when committing or checking out. Doing the latter is difficult, error-prone and slow when done from scripts.

Instead, similarly to git hash-object, --no-filter can be added to git add to enable temporarily disabling filtering in an easy to use way.

The use case here is mostly non-interactive use in scripts creating Git trees that need to exactly correspond to a working directory regardless of whether or not they have any .gitattributes files.

For example, for git-buildpackage or dgit, which facilitate Git workflows with Debian packages, want to ensure the contents of the packages can be exactly reproduced, which is difficult if the upstream’s tarball has .gitattributes. It is possible to "defuse" the attributes as demonstrated above, but this will break if the user modifies the .git/i/a file or if Git adds more attribute-based conversions. This is what dgit currently does, and this is what git-buildpackage will soon do too.

Of course, this patch set only addresses staging files. While working on a patch to git-buildpackage to reproducibly import the contents of tarballs, I realised that the only realistic way seem to do that is to use hash-object + update-index manually, which is likely to come with a performance drop compared to git add (which is what gbp currently uses). A workaround might be to use Dulwich (which would allow to do hash-object without fork/exec) or perhaps GitPython (which I haven’t really looked into), or maybe to use git fast-import, but all of these alternatives are quite complex and don’t guarantee the same performance.

Adding a new option to git add allows to keep the performance without having to ensure attributes are set to the right values. The attributes will likely have to be adjusted anyway for user’s convenience, but at least if they modify them afterwards, the tools won’t break.

These patches:
 * Add new flag ADD_CACHE_RAW to add_to_index()
 * Add new flag HASH_RAW to index_fd()
 * Make git hash-object use the new HASH_RAW flag for consistency
 * Add tests for the new git-add option.
 * Update the git-add manpage describing the new option and pointing out
   it’s tricky to use.
 * Expand the relevant FAQ entry adding --no-filters as yet one more reason
   for perpetually modified files to appear.
Changes since v1:
 * Removed an extra space left in the option definition. Jessica Clarke on
   GitHub pointed out the inconsistent formatting, but contrary to the
   suggestion I updated the style to the more widespread variation: "(0,"
   occurs at least 689 times across the codebase, while "( 0" only at most
   23.
 * Expanded the option description to warn users about potentially confusing
   situations (pointed out by brian m. carlson)
 * Expanded the FAQ entry to mention the new option as one of the cause of
   perpetually modified files.
Andrej Shadura (2):
  add: add option --no-filters to disable attribute-based filtering
  hash-object: use the new HASH_RAW flag instead of setting path to NULL
 Documentation/git-add.txt | 10 ++++++++-
 Documentation/gitfaq.txt  |  7 ++++++
 builtin/add.c             |  3 +++
 builtin/hash-object.c     | 17 ++++++---------
 cache.h                   |  2 ++
 object-file.c             |  2 +-
 read-cache.c              |  3 +++
 t/t2205-add-no-filters.sh | 46 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 78 insertions(+), 12 deletions(-)
 create mode 100755 t/t2205-add-no-filters.sh
base-commit: 2283e0e9af55689215afa39c03beb2315ce18e83
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-880%2Fandrewshadura%2Fgit-add-no-filters-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-880/andrewshadura/git-add-no-filters-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/880
Range-diff vs v1:
 1:  cf8eb886a1e2 ! 1:  1d84503fff48 add: add option --no-filters to disable attribute-based filtering
     @@ Documentation/git-add.txt: for "git add --no-all <pathspec>...", i.e. ignored re
      +--no-filters::
      +	Add the contents as is, ignoring any input filter that would
      +	have been chosen by the attributes mechanism, including the end-of-line
     -+	conversion.
     ++	conversion. Note that this option is not intended for interactive use,
     ++	since files added this way will always show up as modified if Git were
     ++	to apply transformations to them, making the situation potentially
     ++	very confusing.
      +
       --chmod=(+|-)x::
       	Override the executable bit of the added files.  The executable
       	bit is only changed in the index, the files on disk are left
      
     + ## Documentation/gitfaq.txt ##
     +@@ Documentation/gitfaq.txt: following on an otherwise clean working tree:
     + ----
     + $ git add --renormalize .
     + ----
     +++
     ++Another situation where perpetually modified may appear on any platform is when
     ++a file has been committed without running any filters (including the end-of-line
     ++conversion), but the `.gitattributes` file states that this file requires a
     ++conversion.  In this case, you can either renormalize the files if this happened
     ++by mistake, or modify `.gitattributes` or `$GIT_DIR/info/attributes` as described
     ++above to exempt the file from the conversion if this was intentional.
     + 
     + [[recommended-storage-settings]]
     + What's the recommended way to store files in Git?::
     +
       ## builtin/add.c ##
      @@ builtin/add.c: static const char * const builtin_add_usage[] = {
       static int patch_interactive, add_interactive, edit_interactive;
 2:  0e113e958b35 ! 2:  810d4005fe8f hash-object: use the new HASH_RAW flag instead of setting path to NULL
     @@ builtin/hash-object.c: int cmd_hash_object(int argc, const char **argv, const ch
       		OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
       		OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
      -		OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
     -+		OPT_BIT(0 , "no-filters", &flags, N_("store file as is without filters"),
     ++		OPT_BIT(0, "no-filters", &flags, N_("store file as is without filters"),
      +			HASH_RAW),
       		OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")),
       		OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
-- 
gitgitgadget
Previous: brian m. carlsonNext: Andrej Shadura via GitGitGadget
Message 8 of 11 in “Add --no-filters option to git-add”
  1. 0/2 Add --no-filters option to git-addAndrej Shadura via GitGitGadget, Feb 19, 2021
  2. 1/2 add: add option --no-filters to disable attribute-based filteringAndrej Shadura via GitGitGadget, Feb 19, 2021
  3. 2/2 hash-object: use the new HASH_RAW flag instead of setting path to NULLAndrej Shadura via GitGitGadget, Feb 19, 2021
  4. brian m. carlsonFeb 19, 2021
  5. Andrej ShaduraFeb 20, 2021
  6. Andrej ShaduraFeb 20, 2021
  7. brian m. carlsonFeb 20, 2021
  8. 0/2 Add --no-filters option to git-addAndrej Shadura via GitGitGadget, Feb 20, 2021
  9. 1/2 add: add option --no-filters to disable attribute-based filteringAndrej Shadura via GitGitGadget, Feb 20, 2021
  10. 2/2 hash-object: use the new HASH_RAW flag instead of setting path to NULLAndrej Shadura via GitGitGadget, Feb 20, 2021
  11. Junio C HamanoFeb 20, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.