Skip to content

Instantly share code, notes, and snippets.

@wizioo
Last active July 22, 2024 00:18
Show Gist options
  • Save wizioo/c89847c7894ede628071 to your computer and use it in GitHub Desktop.
Save wizioo/c89847c7894ede628071 to your computer and use it in GitHub Desktop.
HowTo have specific .gitignore for each git branch

How to have specific .gitignore for each git branch

Objective

My objective is to have some production files ignored on specific branches. Git doesn't allow to do it.

Solution

My solution is to make a general .gitignore file and add .gitignore.branch_name files for the branches I want to add specific file exclusion. I'll use post-checkout hook to copy those .gitignore.branch_name in place of .git/info/exclude each time I go to the branch with git checkout branch_name.

Steps

  1. Create new .gitignore files for each branch and name it like this : .gitignore.branch_name
  2. In your git repo, go to .git/hooks/
  3. Edit or create post-checkout file and copy the content found in this gist.
  4. Don't forget to make it executable with chmod 755 post-checkout
  5. Just go to the branch you want and type git status: TADAAA !
#!/bin/sh
old_ref=$1
new_ref=$2
branch_switched=$3
if [[ $branch_switched != '1' ]]
then
exit 0
fi
echo "---- POST CHECKOUT ----"
current_branch=$(git rev-parse --abbrev-ref HEAD)
hook_dir=$(dirname $0)
root_dir="$(pwd -P)"
info_dir="$root_dir/.git/info"
exclude_target='.gitignore'
if [[ -f "$root_dir/$exclude_target.$current_branch" ]]
then
echo "Prepare to use .gitignore.$current_branch as exclude file"
exclude_target=.gitignore.$current_branch
fi
cd "$info_dir"
rm exclude
#ln -s $exclude_target exclude
echo "Copy .gitignore.$current_branch file in place of exclude"
cp "$root_dir/$exclude_target" exclude
echo "--- POST CHECKOUT END ---"
@cxspxr
Copy link

cxspxr commented Sep 27, 2018

thanks, mate!

@tiagofrancafernandes
Copy link

Thank you!
I had a problem
.git/hooks/post-checkout: 7: .git/hooks/post-checkout: [[: not found
but solved using #!/bin/bash instead of #!/bin/sh.

@mluerig
Copy link

mluerig commented May 9, 2020

(please ignore my previous comments [deleted]- they were written on a friday afternoon when I was dumb and slow)

good stuff, works like a charm!

@amoh-godwin
Copy link

You have to do:
git checkout
on the repo, after you are done with step 4. On windows you don't need step 4.
You can also delete the file .gitignore.branch_name after you are done with git checkout.

@amoh-godwin
Copy link

@wizioo
The entire internet is confused as to how to go about this, your answer is beautiful.
Please turn this into an article somewhere.

@braindotai
Copy link

@wizioo
This is literally gold man, thanks a ton for this. I almost lost the hope to do something like this after scratching my head for 3 hours.

@StitiFatah
Copy link

Thanks for script, working as intended on arch

@isaacwein
Copy link

if my branch name has a dot in it for example branch.name it won't make sense to use .gitignore.branch.name i will rather suggest .branch.name.gitignore

@AhmedAbdEllatiif
Copy link

Awesome solution

@denOldTimer
Copy link

Hi there I cannot do step four without getting an error

fatal: this operation must be run in a work tree

@amoh-godwin
Copy link

@denOldTimer you must be in the right directory.
The post-checkout file must be in the .git/hooks/ directory

@Tealk
Copy link

Tealk commented Mar 8, 2021

I have revised the whole thing and corrected the spelling
See also: https://github.com/koalaman/shellcheck/wiki

For what are the variables "old_ref" "new_ref" and "hook_dir" in the scirpt eig. because these are not used at all?

Here is the adapted version (untested)
https://gist.github.com/Tealk/13ec8effe72f45f45165143cc64a3048

@DianiSN
Copy link

DianiSN commented Apr 20, 2021

Hi there I cannot do step four without getting an error

fatal: this operation must be run in a work tree

You have to be inside the repository tree and not the .git directory to run step 4.

@amoh-godwin
Copy link

@DianiSN
You have to be in the .git/hooks/ directory

@DianiSN
Copy link

DianiSN commented Apr 21, 2021

@DianiSN
You have to be in the .git/hooks/ directory

Yes, to make the hook but if you want to checkout you have to be in the repository tree and not the hooks directory. Hence why I replied to the comment that mentioned the fatal error. They got that error because they ran git checkout <branch> inside the /.git/hooks directory and not in the main repository directory.

@amoh-godwin
Copy link

@DianiSN true I remember encountering the same error.

@Sudarsanankr
Copy link

Hi

@amoh-godwin
Copy link

...

@hyperfield
Copy link

hyperfield commented Aug 15, 2021

Thank you for the script. Can you please clarify the following error message? I'd like to figure out how to properly use your script.

git checkout web
Already on 'web'
.git/hooks/post-checkout: 7: [[: not found
---- POST CHECKOUT ----
.git/hooks/post-checkout: 18: [[: not found
Copy .gitignore.web file in place of exclude
--- POST CHECKOUT END ---

I've tried this:
cp .gitignore.web .git/info/exclude
No luck yet.

@dberardo-com
Copy link

dberardo-com commented Jun 6, 2022

2 questions here:

  1. is there any way to commit the git hook on the remote ? (using github/gitlab?)
  2. can we have only one gitignore file for a specific branch and not 1 gitignore for each branch in the repo (which might be too many to keep track of) ?

i am asking this because if one uses only one remote, no matter what the client does ignore, the "per-branch" ignored folders will be found on all branches on the remote, which strongly limits the power of this solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment