git


My .gitignore file is ignored by git and it does not work

Some times, even if you haven’t added some files to the repository, git seems to monitor them even after you add them to the .gitignore file.

This is a caching issue that can occur and to fix it, you need to clear your cache.

NOTE : Before proceeding with this solution, commit all changes you do not want to lose!

.. then execute the following commands from the root folder of your repository:
The following, will untrack every file that is in your .gitignore:

git rm -r --cached .;
git add .;
git commit -m "Untracked files issue resolved to fix .gitignore";

git-rm removes files from the index, or from the working tree and the index. git rm will not remove a file from just your working directory. (There is no option to remove a file only from the working tree and yet keep it in the index; use /bin/rm if you want to do that.) The files being removed have to be identical to the tip of the branch, and no updates to their contents can be staged in the index, though that default behavior can be overridden with the -f option. When --cached is given, the staged content has to match either the tip of the branch or the file on disk, allowing the file to be removed from just the index.

-r allows recursive removal when a leading directory name is given.

--cached unstages and removes paths only from the index. Working tree files, whether modified or not, will be left alone.

From: git-rm

To stop tracking a single file file but not delete it from your filesystem use the following:

git rm --cached <file>;

Another issue: file removed from .gitignore filters does not appear to be tracked

When you remove something from .gitignore file and the file does not appear to be tracked, you can add it manually as follows:

git add -f <file>;
git commit -m "Re-Adding ignored file by force";


How to add untracked files to a git patch

Recently, we had to create a git patch for the deployment of a 3rd party repository in our code.
Some of the changes we had to apply using the patch mechanism was the creation of a few new files.
We did not want to have an external script to copy the new files to the appropriate locations, so we had to include those new files in the git patch somehow.
The git diff command (with the parameter -p or --patch) that generates the patch, it ignored the untracked files and so they did not appear in the patch.
To make the untracked files visible to the git diff command, we staged them (using git add) and then used the following command to create the patch:

git diff --patch --staged;

git diff [--options] --cached [<commit>] [--] [<path>...]
git diff [--options] --staged [<commit>] [--] [<path>...]
Adding the parameter --staged or --cached allows you to view the changes you staged for the next commit relative to the named <commit>. Typically you would want comparison with the latest commit, so if you do not give <commit>, it defaults to HEAD. If HEAD does not exist (e.g. unborned branches) and <commit> is not given, it shows all staged changes. --staged is a synonym of --cached.
From: man git-diff

In the end our commands to create the patch with the new files and apply it on a new clone of the 3rd party repository was as follows:

#In the folder of the modified repository, where the new files are staged
git diff -p --staged > ~/new.file.patch.diff;
#In the folder of the new clone of the repository, where the new files need to be created
git apply ~/new.file.patch.diff;


Ignore all edits to a file that is committed in git

Recently, we were working on a project that had committed in the source code a configuration file. That configuration file had hard-coded the production system values, so we had to modify them to the development system values before using it.

To avoid committing the configuration file with the development parameters by accident, we instructed git to ignore any changes that were made to it using the following command.

git update-index --assume-unchanged <file>;

By doing so, git assumed that the file was always unchanged and it never showed up in the git status results nor was staged when git add . was used etc.

After we were done with development (and whenever we needed to pull the branch for changes or checkout another branch) we removed the file from the list of ignored files using the following command.

git update-index --no-assume-unchanged <file>;

Using this command, git would start again to monitor changes to the file and merge it or update it or push it when needed as it would normally do for any file not included in the .gitignore file. The best part of this trick is that you do not have to update the .gitignore file to achieve the task of ignoring a file.

More information

git update-index modifies the index or directory cache. Each file mentioned is updated into the index and any unmerged or needs updating state is cleared.

--[no-]assume-unchanged When these flags are specified, the object names recorded for the paths are not updated. Instead, these options set and unset the “assume unchanged” bit for the paths. When the “assume unchanged” bit is on, Git stops checking the working tree files for possible modifications, so you need to manually unset the bit to tell Git when you change the working tree file. This is sometimes helpful when working with a big project on a filesystem that has very slow lstat(2) system call (e.g. cifs).

This option can be also used as a coarse file-level mechanism to ignore uncommitted changes in tracked files (akin to what .gitignore does for untracked files). Git will fail (gracefully) in case it needs to modify this file in the index e.g. when merging in a commit; thus, in case the assumed-untracked file is changed upstream, you will need to handle the situation manually.

From: man git-update-index

Bonus

In case you are wondering on how to see which files are currently ignored in your local repository copy by the git update-index --assume-unchanged <file>; command, you can use the following code:

git ls-files -v | grep -e '^[[:lower:]]';

git ls-files -v will print out all objects that git knows and the -v parameter will print all flags associated with them. The files that are ignored because of the
git update-index --assume-unchanged <file>; command will be printed each one on a different line that starts with a lower case character. So, to get all files that are ignored by the git update-index --assume-unchanged <file>; command, we need to grep the results of git ls-files -v for lines that start with a lower case.

git-ls-files shows information about files in the index and the working tree.
It merges the file listing in the directory cache index with the actual working directory list, and shows different combinations of the two.

-v Similar to -t (below), but use lowercase letters for files that are marked as assume unchanged (see git-update-index(1)).

-t This feature is semi-deprecated. For scripting purpose, git-status(1)–porcelain and git-diff-files(1)–name-status are almost always superior alternatives, and users should look at git-status(1)–short or git-diff(1)–name-status for more user-friendly alternatives.
This option identifies the file status with the following tags (followed by a space) at the start of each line:

An additional interesting parameter for git ls-files is
-i, --ignored Shows only ignored files in the output. When showing files in the index, it prints only those matched by an exclude pattern. When showing “other” files, it shows only those matched by an exclude pattern.

--exclude-standard Add the standard Git exclusions: .git/info/exclude, .gitignore in each directory, and the user’s global exclusion file.
From: man git-ls-files

Examples for git ls-files -i, –ignored and –exclude-standard

# Show files in the index that are ignored because of patterns in .gitignore
git ls-files --ignored --exclude-from=.gitignore;
# Show other (i.e. untracked) files that are ignored because of patterns in .gitignore
git ls-files --ignored --other --exclude-from=.gitignore;
# Show files in the index that are ignored because of patterns in any of the standard git exclusions.
git ls-files --ignored --exclude-standard;
# Show other (i.e. untracked) files that are ignored because of patterns in any of the standard git exclusions.
git ls-files --ignored --exclude-standard --other;


Git: Perform a stash addition using a custom/meaningful message

Did you ever wonder “Is there more to git stash?”, we did!
We wanted to see if there is a way to manually set the stash message to something meaningful instead of the automated message that derives from the last commit.

Fortunately, there is the command git stash save "Meaningful message"; which allows you to add new changes in your stash and at the same time use a custom message.

By using the git stash save "custom message"; command you will be enhancing the results of the git stash list; command as it will contain more useful information for you.

Example

$ git status;
On branch master
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: me

no changes added to commit (use "git add" and/or "git commit -a")
$ git stash save "custom message";
Saved working directory and index state On master: your message here
$ git stash list 
[email protected]{0}: On master: custom message
$ git stash show
 me | 1 +
 1 file changed, 1 insertion(+)

Find all git repositories and perform a pull operation on them.

The following command will find all git projects in your home folder and perform a pull operation on them.

find ~ -name ".git" -type d -exec bash -c "echo '{}' && cd '{}'/.. && git pull" \;

The above command is based on finding the .git folders that exist in any clone of a git repository. Once a .git folder is found, it will navigate to its parent folder where it will perform the pull request.

Bonus – Automate the procedure using a cron job

The following entry in crontab allows us to periodically perform a pull request on all the cloned repositories that we have in a specific folder. Specifically, it will perform this operation once every five minutes.

*/5    *    *    *    *    cd /home/bytefreaks/Projects; find . -name ".git" -type d -exec bash -c "echo '{}' && cd '{}'/.. && git pull" \; &> /tmp/bf.git.log

Please note that it would be easier to use an ssh key that does not have a password for this automation.
If you do not, the you will need to either pass the password via this configuration line (not recommended) or have a key agent running to provide the password for the key.

Forcing user to remove trailing spaces in git

There are simple ways to force the user in removing trailing spaces before committing code in git using hooks.
Below we will present a solution that is applied at the local computer before the commit stage, which each developer needs to perform in each repository clone they own.
Note: If you would like to have the hooks on the server, you will need extra access rights to modify the hooks on the remote machine, maybe you will even need your systems administrator to configure it.

Solution

Attached you will find a file named pre-commit ( pre-commit (compressed) (3 downloads) ) it is a hook that get applied before the user is allowed to even commit.
That file you need to copy it (after you extract it) in the .git/hooks folder of your cloned repositories and you are done!

What this script does is simple, if there are whitespace errors, it prints the offending file names and fails.
What are considered whitespace errors is controlled by core.whitespace configuration.
By default, trailing whitespaces (including lines that solely consist of whitespaces) and a space character that is immediately followed by a tab character inside the initial indent of the line are considered whitespace errors.

In case you need to commit files that have whitespace errors, you can bypass the checks that are applied by the hooks using the --no-verify flag as follows:

git commit -m "Some informative message" --no-verify;

There are more ways to achieve this result, others are more verbose but this one is the simplest and more flexible as you can configure it using the git configuration variables.

pre-commit (compressed) (3 downloads)

#!/bin/sh
#
# This hook script verifies that there are no whitespace errors in the files to be committed

if git rev-parse --verify HEAD >/dev/null 2>&1
then
 against=HEAD
else
 # Initial commit: diff against an empty tree object
 against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Redirect output to stderr.
exec 1>&2

# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

pre-commit (compressed) (3 downloads)


How to execute `find` that ignores .git directories

Trying to find a source code file by its content using find and -exec grep, can some times result in getting results from the repository .git folders as well.

This behavior not only does it provide results you do not need but it also makes your search slower.
Below, we propose a couple of solutions on how to make a more efficient search.

Example 1: Ignore all .git folders no matter where they are in the search path

For find to ignore all .git folders, even if they appear on the first level of directories or any in-between until the last one, add -not -path '*/\.git*' to your command as in the example below.
This parameter will instruct find to filter out any file that has anywhere in its path the folder .git. This is very helpful in case a project has dependencies in other projects (repositories) that are part of the internal structure.

find . -type f -not -path '*/\.git/*';

Note, if you are using svn use:

find . -type f -not -path '*/\.svn/*';

Example 2: Ignore all hidden files and folders

To ignore all hidden files and folders from your find results add -not -path '*/\.*' to your command.

find . -not -path '*/\.*';

This parameter instructs find to ignore any file that has anywhere in its path the string /. which is any hidden file or folder in the search path!


How to undo a Git commit that was not pushed 1

To undo a Git commit that was not pushed, you are given a few major options:

  1. Undo the commit but keep all changes staged
  2. Undo the commit and unstage the changes
  3. Undo the commit and lose all changes

Method 1: Undo commit and keep all files staged

In case you just want to undo the commit and change nothing more, you can use

git reset --soft HEAD~;

This is most often used to make a few changes to your latest commit and/or fix your commit message. Leaves working tree as it was before reset.
soft does not touch the index file or the working tree at all (but resets the head to the previous commit). This leaves all your changed files Changes to be committed, as git status would put it.

Method 2: Undo commit and unstage all files

In case you want to undo the last commit and unstage all the files you can use the following

git reset HEAD~;

or

git reset --mixed HEAD~;

mixed will reset the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action.

Method 3: Undo the commit and completely remove all changes

The following method will undo the commit and revert all changes so that your state is exactly as it was before you started making changes.

git reset --hard HEAD~;

hard resets the index and working tree. Any changes to tracked files in the working tree since the previous commit are discarded.

 

Note: In case you just want to rewrite the commit message, you could use git –amend instead.