828

I have a bunch of files in a changeset, but I want to specifically ignore a single modified file. Looks like this after git status:

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

Is there a way I can do git add but just ignore the one text file I don't want to touch? Something like:

git add -u -except main/dontcheckmein.txt
Scott Weldon
  • 9,673
  • 6
  • 48
  • 67
user291701
  • 38,411
  • 72
  • 187
  • 285
  • 2
    what is the purpose of `-u` flag it's working without `-u` – Saad Abbasi Sep 17 '20 at 03:23
  • 3
    From man git add: -u, --update "Update the index just where it already has an entry matching . This removes as well as modifies index entries to match the working tree, but adds no new files. ..." – Simeon Feb 02 '21 at 09:14
  • 5
    @SaadAbbasi Maybe this table from https://github.com/git-guides/git-add is even better to tell what -u does: `git add -u: stages new and modified files only, NOT deleted files` – Simeon Feb 02 '21 at 09:28
  • 3
    if you have untracked files, the -u option takes care that those untracked files are not added. git add --all would add those files as well. – Simeon Feb 02 '21 at 09:37

19 Answers19

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

Note: Git has subsequently added special syntax for this, which is explained in other answers.

Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • 46
    how do I exclude the whole folder? -- main or main/ or main/* ? – Alan Coromano Nov 23 '13 at 09:08
  • 16
    @MariusKavansky You can use all of these forms. If you use `main/*` it is necessary to add `--` in front of it to let git know that it is a path. The other two variants work without including the two dashes. (Tested in command prompt on Windows 7 with msysGit) – Dennis van der Schagt Nov 08 '14 at 14:06
  • 2
    If you have some folders you want to exclude that contain a huge amount of files or other folders: temporarily add them to your gitignore. performing a ```git reset``` for those folders afterwards will still work, but it will take git a long while to add the big folders. – Michahell May 13 '15 at 13:24
  • 2
    So, there's no one-liner? – BroVic Jul 13 '18 at 12:54
  • 13
    @Ben Jackson would be nice to comment each line, don't you think? – ed1nh0 Sep 25 '18 at 12:58
  • Worked fine for me :) – Naveen Kumar V Mar 22 '20 at 18:37
  • After adding all files to the staging area via `git add -u` typing `git status` will suggest you to `git restore --staged main/dontcheckmein.txt` Why did @BenJackson suggest reset instead? – Simeon Mar 10 '21 at 14:57
  • 2
    @Simeon `git reset` always did two things (switching branches, and restoring files). When this answer was written 10 years ago, `git restore` didn't exist (it was added in 2019). Now you could also write this answer in terms of `git restore` because it does some of the same things as `reset` – Ben Jackson Mar 10 '21 at 18:18
  • So, there's not really a way to do it then. Just add all the things and then remove – CodeFinity May 24 '21 at 15:08
  • @cateyes answer should be accepted. This gives the same result but doesn't really do what the question asks. For example, when adding a large file this answer will still need a lot of time to add the large file, just to remove it later. – Marko May 06 '22 at 10:16
  • 1
    "which is explained in other answers" of which there are 22, so can you update to give us a hint, please? Thanks! – Dan Rosenstark May 24 '22 at 15:46
312

Now git supports exclude certain paths and files by pathspec magic :(exclude) and its short form :!. So you can easily achieve it as the following command.

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

Actually you can specify more:

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

For Mac and Linux, surround each file/folder path with quotes

git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'
Oleg Kokorin
  • 2,288
  • 2
  • 16
  • 28
cateyes
  • 5,208
  • 2
  • 24
  • 31
  • 56
    This is excellent! Note that on Linux, you need to quote the `:!...` clauses to keep the shell from complaining. So, for example: `git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'`. – Martin_W Jan 09 '19 at 22:33
  • Is there something like `:!/path/to/(file1|file2)`? – seeker_of_bacon Jul 03 '19 at 11:46
  • 5
    This collides with something in zsh, doesn't work for me on macOS and latest git. – Merlin Dec 05 '19 at 23:30
  • @Merlin i had same problem with mac until i used the quotes as mentioned by Martin_W comment, then it worked for me – luckyguy73 May 06 '20 at 20:34
  • 1
    Without the quotes around the `:!...`, I was getting `event not found` error in windows 10 git bash as well. Look @Martin_W's comment – Nuhman Jun 20 '20 at 19:12
  • 1
    Note that the path is relative to the current directory! i.e. if you're in `./path/`, use just `git add --all -- ':!to/file1'` – Paul Aug 07 '20 at 22:38
  • 5
    This is the best answer. If it ts needed to exclude a large folder with a lot of files, adding and resetting takes ages. `git add -- . ':!'` is way faster. – jolammi Jan 29 '21 at 06:37
  • 1
    Would `git add . --:!path/to/file` work too? Is there a distinction between `git add .` and `git add -- .`? Are the first `--` before the `.` needed? – Matt Jun 24 '21 at 03:12
  • 1
    @jolammi I also see that you have the `--` only *before* the `.`, but not before the excluded path? I'm just trying to understand where the `--`are redundant, and where they're actually required. – Matt Jun 24 '21 at 03:18
  • I had to escape the exclamation mark, otherwise it failed with "event not found". `git add -- . :\!main/dontcheckmein.txt` – Richard Whitehead Nov 18 '21 at 15:56
  • in mac you should use `--all` instead of `--all--` – poweredbygt Jun 16 '23 at 12:41
192

1) To start ignoring changes to a single already versioned file

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

and to undo that git update-index --no-assume-unchanged "main/dontcheckmein.txt"

github docs to ignore files

2) To completely ignore a specific single file preventing it from being created at repository

First, look at this stackoverflow post: Git global ignore not working

In .gitignore, add the relative path to the file without leading ./.

So, if your file is at MyProject/MyFolder/myfile.txt, (where .git is also in the MyProject folder), add MyFolder/myfile.txt to your at .gitignore file.

You can confirm what rules are associated with ignore via git check-ignore "MyFolder/myfile.txt"

About global ignore

That link talks about ~/.gitignore_global, but the file is related to your project. So, if you put the exclude pattern MyFolder/myfile.txt in ~/.gitignore_global, it will work but will not make much sense...

On the other hand, if you setup your project with git config core.excludesfile .gitignore where .gitignore is in MyProject, the local file will override ~/.gitignore_global, which can have very useful rules...

So, for now, I think it's best to make some script to mix your .gitignore with ~/.gitignore_global at .gitignore.

One last warning
If the file you want to ignore is already in the repository, this method will not work unless you do this: git rm "MyFolder/myfile.txt", but back it up first, as it will be removed locally also! You can copy it back later...

SherylHohman
  • 16,580
  • 17
  • 88
  • 94
Aquarius Power
  • 3,729
  • 5
  • 32
  • 67
  • 6
    You can use `git rm --cached MyFolder/myyfile.txt` to remove the file from the repository but keep it locally. [Explanation on help.github.com](https://help.github.com/articles/ignoring-files/) – Dennis van der Schagt Nov 08 '14 at 13:55
  • How do I add the files back again? – SagarM May 27 '21 at 11:25
  • I'm wondering where this command `git update-index --assume-unchanged "main/dontcheckmein.txt"` is stored in git folder structure – MaXi32 Jul 24 '21 at 05:39
112

For a File

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

For a folder

git add -u
git reset -- main/*
Rituraj ratan
  • 10,260
  • 8
  • 34
  • 55
  • 19
    why is the -u necessary? why not `git add . && git reset -- main/*`? –  Sep 20 '18 at 21:34
  • 3
    The -u option updates the index just where it already has an entry matching . This removes as well as modifies index entries to match the working tree, but adds no new files. If no is given when -u option is used, all tracked files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories). – Farhad Mammadli Nov 20 '18 at 09:28
  • 17
    Can anyone explain why the -u is necessary in language that non-git pros will understand? – Patrick Sep 21 '19 at 16:51
  • 7
    -u is used to reference your current branch you're pushing to. You will no longer need to type ```git push origin master``` in your next push, just ```git push``` and git will know that is it in master branch. Hope it helps. – Pepeng Hapon Sep 25 '19 at 02:49
25

Git provides :(exclude) pathspecs prefix for paths to be excluded.

Its short magic signature is :^.
Documentation: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-exclude

git add . :^main/dontcheckmein.txt

Some answers to this thread mention :!, which would also work, but only with quotes. In general, ! is considered a horrible character for shell expansion.


If you are like me — always review what is going to be committed using -p flag within the git add command — :^ magic signature works like a charm, too:

git add -p . :^main/dontcheckmein.txt
Nik Sumeiko
  • 8,263
  • 8
  • 50
  • 53
22

While Ben Jackson is correct, I thought I would add how I've been using that solution as well. Below is a very simple script I use (that I call gitadd) to add all changes except a select few that I keep listed in a file called .gittrackignore (very similar to how .gitignore works).

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

And this is what my current .gittrackignore looks like.

project.properties

I'm working on an Android project that I compile from the command line when deploying. This project depends on SherlockActionBar, so it needs to be referenced in project.properties, but that messes with the compilation, so now I just type gitadd and add all of the changes to git without having to un-add project.properties every single time.

Anthony Naddeo
  • 2,497
  • 25
  • 28
  • I didn't know what `--` was until your comment. According to the man pages, its optional and doesn't change the result of the command (at least in this case). This question seems to support that, http://stackoverflow.com/questions/17800994/git-two-dashes-means-with-no-more-options. Correct me if I'm wrong, but it seems that it means "treat anything after `--` as arguments, not options / switches" – Anthony Naddeo Dec 19 '13 at 20:41
  • Nice use of `--` in `git checkout` I see in that question. I didn't know what the double dash was until this exchange of ours, too. I wonder if the `git checkout` ambiguity between branches and files could affect, in this or a different form, `git reset` also. – Giulio Piancastelli Dec 20 '13 at 00:06
18

To keep the change in file but not to commit I did this

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

to verify the file is excluded do

git status

gsumk
  • 809
  • 10
  • 15
  • After adding all files to the staging area via `git add .` typing `git status` will suggest you to `git restore --staged main/dontcheckmein.txt` Why did @gsumk suggest `reset` instead? – Simeon Mar 10 '21 at 13:39
14
git add .
git reset main/dontcheckmein.txt
Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94
7

Use git add -A to add all modified and newly added files at once.

Example

git add -A
git reset -- main/dontcheckmein.txt
Dhanuka Nuwan
  • 690
  • 8
  • 14
7

We can add all the files and exclude the file which has to be removed by git reset.

git add .
git reset -- <file_name_to_exclude>
Tom Taylor
  • 3,344
  • 2
  • 38
  • 63
4

add all files

git add .

get file path to paste below

git status

remove from the commit

git reset -- file/to/path/file-to-ignore.txt

Nick
  • 51
  • 1
  • 3
3

For the specific case in the question, easiest way would be to add all files with .c extension and leave out everything else:

git add *.c

From git-scm (or/and man git add):

git add <pathspec>…​

Files to add content from. Fileglobs (e.g. *.c) can be given to add all matching files. <...>

Note that this means that you could also do something like:

git add **/main/*

to add all files (that are not ignored) that are in the main folder. You can even go wild with more elaborate patterns:

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

The above will add all files that are in s(any char)c folder and have Service somewhere in their filename.

Obviously, you are not limited to one pattern per command. That is, you could ask git to add all files that have an extension of .c and .h:

git add *.c *.h

This link might give you some more glob pattern ideas.

I find it particularly useful when I'm making many changes, but still want my commits to stay atomic and reflect gradual process rather than a hodgepodge of changes I may be working at the time. Of course, at some point the cost of coming up with elaborate patterns outweighs the cost of adding files with simpler methods, or even one file at a time. However, most of the time I'm easily able to pinpoint just the files I need with a simple pattern, and exclude everything else.

By the way, you may need to quote your glob patterns for them to work, but this was never the case for me.

cegas
  • 2,823
  • 3
  • 16
  • 16
2

Try this:

git checkout -- main/dontcheckmein.txt
Akber Iqbal
  • 14,487
  • 12
  • 48
  • 70
Abdullah Aman
  • 1,314
  • 11
  • 11
1

Not directly what you asked as it does not achieve it in one command but the result should be what you desire.

After adding all files to the staging area via

git add -u

typing git status will suggest you to

git restore --staged main/dontcheckmein.txt
Simeon
  • 748
  • 1
  • 9
  • 26
0

I use git add --patch quite a bit and wanted something like this to avoid having to hit d all the time through the same files. I whipped up a very hacky couple of git aliases to get the job done:

[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' )"

In my case I just wanted to ignore certain minified files all the time, but you could make it use an environment variable like $GIT_EXCLUDE_PATTERN for a more general use case.

Chris
  • 2,174
  • 28
  • 37
0

Changes to be committed: (use "git reset HEAD ..." to unstage)

colin rickels
  • 659
  • 2
  • 6
  • 9
0

If you want to ignore a particular file every time there are three effective solutions that don't involve .gitignore.

  1. Add the file you want to ignore to .git/info/exclude. It works just like your .gitignore, except that the configuration is specific to your machine.

  2. Reset the file you want to using a pre-commit git hook. For example:

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

    A pre-commit hook runs just before a commit. So your files can be automatically reset before each 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. The third way is to update the index for a particular file.

    $ git update-index --assume-unchanged src/main/resources/log4j.properties
    
TheChetan
  • 4,440
  • 3
  • 32
  • 41
0

you can use recommend of git

add all file change and restore file not want push

git add .
git restore --staged <file_not_push>
LinFelix
  • 1,026
  • 1
  • 13
  • 23
DoanLe
  • 1
  • 2
-2

You can try this: git add * && git reset main/dontcheckmein.txt

Rodrigo
  • 111
  • 1
  • 1
  • 9