【问题标题】:Add all files to a commit except a single file?将所有文件添加到提交中,除了单个文件?
【发布时间】:2011-05-27 09:40:39
【问题描述】:

我在变更集中有一堆文件,但我想专门忽略一个修改过的文件。 git status之后的样子:

# modified:   main/dontcheckmein.txt
# deleted:    main/plzcheckmein.c
# deleted:    main/plzcheckmein2.c
...

有没有一种方法可以让git add 忽略我不想碰的一个文本文件?比如:

git add -u -except main/dontcheckmein.txt

【问题讨论】:

  • -u 标志的目的是什么,它在没有 -u 的情况下工作
  • From man git add: -u, --update "在已经有匹配的条目处更新索引。这将删除并修改索引条目以匹配工作树,但是不添加新文件。..."
  • @SaadAbbasi 也许github.com/git-guides/git-add 的这张表更能说明 -u 的作用:git add -u: stages new and modified files only, NOT deleted files
  • 如果您有未跟踪的文件,-u 选项会注意不添加那些未跟踪的文件。 git add --all 也会添加这些文件。

标签: git git-add


【解决方案1】:
git add -u
git reset -- main/dontcheckmein.txt

【讨论】:

  • 如何排除整个文件夹? -- main or main/ or main/* ?
  • @MariusKavansky 您可以使用所有这些表格。如果使用main/*,需要在前面加上--,让git知道它是一个路径。其他两个变体在不包括两个破折号的情况下工作。 (使用 msysGit 在 Windows 7 上的命令提示符下测试)
  • 如果你想要排除一些包含大量文件或其他文件夹的文件夹:暂时将它们添加到你的 gitignore。之后为这些文件夹执行git reset 仍然可以工作,但添加大文件夹需要很长时间。
  • 那么,没有单行吗?
  • @Ben Jackson 会很高兴评论每一行,你不觉得吗?
【解决方案2】:

虽然 Ben Jackson 是正确的,但我想我也会补充一下我是如何使用该解决方案的。下面是我使用的一个非常简单的脚本(我称之为 gitadd)添加所有更改,除了我保留在名为 .gittrackignore 的文件中列出的少数更改(非常类似于 .gitignore 的工作方式)。

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

这就是我当前的.gittrackignore 的样子。

project.properties

我正在开发一个在部署时从命令行编译的 Android 项目。这个项目依赖于 SherlockActionBar,所以需要在 project.properties 中引用它,但这会干扰编译,所以现在我只需键入 gitadd 并将所有更改添加到 git 中,而不必每次都取消添加 project.properties一次。

【讨论】:

  • 在您发表评论之前,我不知道 -- 是什么。根据手册页,它是可选的并且不会改变命令的结果(至少在这种情况下)。这个问题似乎支持stackoverflow.com/questions/17800994/…。如果我错了,请纠正我,但这似乎意味着“将-- 之后的任何内容视为参数,而不是选项/开关”
  • git checkout 中很好地使用-- 我在那个问题中看到了。在我们交换之前,我也不知道双破折号是什么。我想知道分支和文件之间的git checkout 歧义是否会以这种或不同的形式影响git reset
【解决方案3】:

1) 开始忽略对单个已版本化文件的更改

git update-index --assume-unchanged "main/dontcheckmein.txt"

并撤消该git update-index --no-assume-unchanged "main/dontcheckmein.txt"

github docs to ignore files

2) 完全忽略特定的单个文件,阻止它在存储库中创建

首先,看看这个 stackoverflow 帖子:Git global ignore not working

.gitignore 中,添加文件的相对路径,不带前导./

因此,如果您的文件位于 MyProject/MyFolder/myfile.txt(其中 .git 也在 MyProject 文件夹中),请将 MyFolder/myfile.txt 添加到您的 .gitignore 文件中。

您可以通过git check-ignore "MyFolder/myfile.txt"确认哪些规则与忽略相关

关于全局忽略

该链接涉及~/.gitignore_global,但该文件与您的项目相关。所以,如果你把排除模式MyFolder/myfile.txt 放在~/.gitignore_global 中,它会起作用但没有多大意义......

另一方面,如果您使用git config core.excludesfile .gitignore 设置项目,其中.gitignoreMyProject 中,则本地文件将覆盖~/.gitignore_global,它可以有very useful rules...

所以,就目前而言,我认为最好制作一些脚本来将.gitignore~/.gitignore_global 混合在.gitignore

最后一个警告
如果您要忽略的文件已经在存储库中,除非您这样做:git rm "MyFolder/myfile.txt",否则此方法将不起作用,但请先备份它,因为它也会在本地删除!您可以稍后将其复制回来...

【讨论】:

  • 您可以使用git rm --cached MyFolder/myyfile.txt 从存储库中删除文件,但将其保留在本地。 Explanation on help.github.com
  • 如何重新添加文件?
  • 我想知道这个命令git update-index --assume-unchanged "main/dontcheckmein.txt"在git文件夹结构中的存储位置
【解决方案4】:

对于文件

git add -u
git reset -- main/dontcheckmein.txt

对于文件夹

git add -u
git reset -- main/*

【讨论】:

  • 为什么需要 -u?为什么不git add . && git reset -- main/*
  • -u 选项更新索引,它已经有一个匹配 的条目。这会删除并修改索引条目以匹配工作树,但不会添加新文件。如果使用 -u 选项时没有给出 ,则更新整个工作树中的所有跟踪文件(旧版本的 Git 用于限制对当前目录及其子目录的更新)。
  • 谁能用非 git 专业人士能理解的语言解释为什么 -u 是必要的?
  • -u 用于引用您当前推送的分支。您将不再需要在下一次推送中输入git push origin master,只需输入git push,git 就会知道它在 master 分支中。希望对您有所帮助。
【解决方案5】:

我经常使用git add --patch,并且想要这样的东西来避免必须通过相同的文件一直点击d。为了完成工作,我创建了几个非常老套的 git 别名:

[alias]
    HELPER-CHANGED-FILTERED = "!f() { git status --porcelain | cut -c4- | ( [[ \"$1\" ]] && egrep -v \"$1\" || cat ); }; f"
    ap                      = "!git add --patch -- $(git HELPER-CHANGED-FILTERED 'min.(js|css)$' || echo 'THIS_FILE_PROBABLY_DOESNT_EXIST' )"

在我的例子中,我只是想一直忽略某些缩小的文件,但你可以让它使用像 $GIT_EXCLUDE_PATTERN 这样的环境变量来获得更一般的用例。

【讨论】:

    【解决方案6】:

    试试这个:

    git checkout -- main/dontcheckmein.txt
    

    【讨论】:

    【解决方案7】:

    对于问题中的特定情况,最简单的方法是添加所有具有 .c 扩展名的文件,而忽略其他所有文件:

    git add *.c
    

    来自git-scm(或/和man git add):

    git add …​

    要从中添加内容的文件。可以给出 Fileglobs(例如 *.c)来添加所有匹配的文件。 <...>

    请注意,这意味着您还可以执行以下操作:

    git add **/main/*
    

    添加main 文件夹中的所有文件(未被忽略的)。您甚至可以使用更复杂的模式来狂野:

    git add **/s?c/*Service*
    

    上面将添加s(any char)c 文件夹中的所有文件,并在其文件名中的某处有Service

    显然,您不限于每个命令使用一种模式。也就是说,您可以要求 git 添加所有扩展名为 .c.h 的文件:

    git add *.c *.h
    

    这个link 可能会给你更多 glob 模式的想法。

    当我进行许多更改时,我发现它特别有用,但仍希望我的提交保持原子性并反映渐进过程,而不是我当时可能正在工作的大杂烩。当然,在某些时候,提出复杂模式的成本超过了使用更简单的方法添加文件的成本,甚至一次添加一个文件的成本。但是,大多数情况下,我可以通过简单的模式轻松地找出我需要的文件,并排除其他所有文件。

    顺便说一句,您可能需要引用您的 glob 模式才能使它们起作用,但对我来说从来没有这种情况。

    【讨论】:

      【解决方案8】:

      使用git add -A 一次添加所有修改和新添加的文件。

      例子

      git add -A
      git reset -- main/dontcheckmein.txt
      

      【讨论】:

        【解决方案9】:

        现在git 支持exclude certain paths and files by pathspec magic :(exclude) 及其缩写形式:!。因此,您可以通过以下命令轻松实现。

        git add --all -- :!main/dontcheckmein.txt
        git add -- . :!main/dontcheckmein.txt
        

        其实你可以指定更多:

        git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
        git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
        

        对于 Mac 和 Linux,用引号将每个文件/文件夹路径括起来

        git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'
        

        【讨论】:

        • 最佳答案,谢谢!至少,就我而言:我只需要排除一种文件类型。
        • 这太棒了!请注意,在 Linux 上,您需要引用 :!... 子句以防止 shell 抱怨。因此,例如:git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'.
        • 这与 zsh 中的某些内容发生冲突,在 macOS 和最新的 git 上对我不起作用。
        • 注意路径是相对于当前目录的!即如果你在./path/,只使用git add --all -- ':!to/file1'
        • 这是最好的答案。如果需要排除包含大量文件的大文件夹,则添加和重置需要很长时间。 git add -- . ':!&lt;path&gt;' 更快。
        【解决方案10】:

        要提交的更改: (使用“git reset HEAD ...”取消暂存)

        【讨论】:

          【解决方案11】:

          为了保留文件中的更改但不提交,我这样做了

          git add .

          git reset -- main/dontcheckmein.txt

          git commit -m "commit message"

          验证文件是否被排除

          git status

          【讨论】:

          • 通过git add .将所有文件添加到暂存区后,输入git status会建议您使用git restore --staged main/dontcheckmein.txt为什么@gsumk建议改为reset
          【解决方案12】:
          git add .
          git reset main/dontcheckmein.txt
          

          【讨论】:

            【解决方案13】:

            你可以试试这个:git add * &amp;&amp; git reset main/dontcheckmein.txt

            【讨论】:

              【解决方案14】:

              我们可以添加所有文件,排除需要通过 git reset 删除的文件。

              git add .
              git reset -- <file_name_to_exclude>
              

              【讨论】:

                【解决方案15】:

                不是你直接问的,因为它不能在一个命令中实现,但结果应该是你想要的。

                将所有文件添加到暂存区后通过

                git add -u
                

                输入 git status 将建议您

                git restore --staged main/dontcheckmein.txt
                

                【讨论】:

                  【解决方案16】:

                  如果你想每次都忽略一个特定的文件,有三种不涉及.gitignore的有效解决方案。

                  1. 将要忽略的文件添加到.git/info/exclude。它和你的.gitignore 一样工作,除了configuration is specific to your machine

                  2. 使用pre-commit git hook 重置您要使用的文件。例如:

                    $ echo 'git reset -- src/main/resources/log4j.properties' >> .git/hooks/pre-commit
                    $ chmod +x .git/hooks/pre-commit
                    

                    预提交挂钩在提交之前运行。因此,您的文件可以在每次提交之前自动重置。

                    $ git status
                    On branch CHANGE-137-notifications-support ...
                    
                    Changes not staged for commit:
                     modified:   Dockerfile
                     modified:   src/main/resources/log4j.properties
                    
                    $ git add .
                    
                    $ git status
                    On branch CHANGE-137-notifications-support ...
                    
                    Changes to be committed:
                     modified:   Dockerfile
                     modified:   src/main/resources/log4j.properties
                    
                    
                    $ git commit -m "Trivial change"
                    
                    Unstaged changes after reset:
                    M    src/main/resources/log4j.properties
                    
                    [CHANGE-137-notifications-support 97cfb3f] Trivial change
                    1 file changed, 3 insertions(+)
                    
                  3. 第三种方法是更新特定文件的索引。

                    $ git update-index --assume-unchanged src/main/resources/log4j.properties
                    

                  【讨论】:

                    【解决方案17】:

                    Git 为要排除的路径提供:(exclude) pathspecs 前缀。

                    它的简短魔术签名是:^
                    文档:https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-exclude

                    git add . :^main/dontcheckmein.txt
                    

                    该线程的一些答案提到了:!,它也可以使用,但只能使用引号。一般来说,! 被认为是用于 shell 扩展的可怕字符。


                    如果您像我一样 — 始终使用 git add 命令中的 -p 标志检查将要提交的内容 — :^ 魔术签名也很有魅力:

                    git add -p . :^main/dontcheckmein.txt
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-10-20
                      • 2017-11-27
                      • 1970-01-01
                      • 2017-11-23
                      相关资源
                      最近更新 更多