Not Possible to switch branch after --skip-worktree
WHAT I WANT TO DO
I have a file which contains sensitive datas so I don't want to push content of this file to remote server.
WHAT I DID?
To achieve this, I made a commit when the file was empty and pushed this empty file to server (GitHub). And then fill the file with sensitive datas and applied git update-index --skip-worktree path/to/file
. But I didn't made any commit.
Now I'm trying to switch my branch but I'm getting this error :
error: Your local changes to the following files would be overwritten by checkout:
path/to/file
Please, commit your changes or stash them before you can switch branches.
Aborting
WHY I USE skip-worktree
INSTEAD OF assume-unchanged
?
I read a few SO questions about this subject, and found Borealid's answer.
--assume-unchanged assumes that a developer shouldn’t change a file. This flag is meant for improving performance for not-changing folders like SDKs.
--skip-worktree is useful when you instruct git not to touch a specific file ever because developers should change it. For example, if the main repository upstream hosts some production-ready configuration files and you don’t want to accidentally commit changes to those files, --skip-worktree is exactly what you want.
After this, I found Jeff's question and VonC's answer. Jeff's problem is almost same with mine, and I followed VonC's solution. However it's not work for me. Maybe because of git version difference. Because that question from 2012. We talked with VonC and he said to ask this as a new question because he couldn't remember answer.
I tried to use --assume-unchanged
and --skip-worktree
together, and soft reseting worktree. But nothing changed.
SO?
Can you help me about my problem ?
Thank you.
I haven't been able to find a neat solution to this, so I'm using a .bat
file to run --no-skip-worktree
on the affected files. I then stash
, switch branch, stash apply
, and then use another .bat
file to run --skip-worktree
on the same files.
It's not nice, but it's the simplest and quickest way I've found so far.
Update:
I've run into this problem again so have created a PowerShell script instead of the .bat
file mentioned above. It will prompt the user whether they want to skip or no-skip the files. Update the two parameters and you're ready to go:
[string]$repoPath = "C:\Fully\Qualified\Path"
[string[]]$filesToSkip = @(
"Local/Path/To/File.txt",
"Local/Path/To/OtherFile.txt"
)
$skipText = Read-Host -Prompt 'Skip files? (y/n)'
$skip = $skipText -like "y"
cd $repoPath
foreach ($file in $filesToSkip)
{
if($skip)
{
Write-Host "Skipping" $file
git update-index --skip-worktree $file
}
else
{
Write-Host "No-skipping" $file
git update-index --no-skip-worktree $file
}
}
Well, this is a cruddy solution, but seems to work reasonably well (though it is only lightly tested):
Create a file named git-checkoutsw
somewhere in your PATH
, with the following content:
#!/bin/bash
ignored=( $(git ls-files -v | grep "^S " | cut -c3-) )
for x in "${ignored[@]}"; do
git update-index --no-skip-worktree -- "$x"
done
git checkout -m $@
for x in "${ignored[@]}"; do
git update-index --skip-worktree -- "$x"
done
The script captures the list of ignored files, unignores them, checks out the new branch with -m
(for merge) and whatever other parameters have been specified, and then ignores them again.
Now you can do git checkoutsw
instead of git checkout
.
I got the same problem and it boiled down to be casued by incoming changes on the file I wanted to assume-unchanged on.
So if I just do no-assume-unchanged on the file, stash it, checkout the latest version, pop my stash, and assume-unchanged again.
So now I'm able to switch branches again.
You can enable sparse checkout and add the file there together with adding the skip-worktree flag (if you add the sparse checkout alone it probably will be deleted).
To exclude a file you should put to sparse-checkout file (see git-read-tree manual):
/*
!unwanted
Then it will not be touched at update (so you don't get content of the other branch there, instead preserving your edits). It might be not what you want.