Question

Here is the situation I'm facing:

A directory full of generated files where commited to the repo by mistake. They obviously shouldn't have been, so I want to remove them:

$ git rm --cached foo/*
$ cat > foo/.gitignore
*
!.gitignore
$ git add foo/
$ git commit -m "Ignored stuff in foo"

This almost solves it, but leaves a different problem. When I want to git fetch && git checkout on the production server, all the generated files in the foo/ directory will be removed. Is there some magic I could do about it on either side? Please not that simply ignoring them is not an option as they can be changed.

Was it helpful?

Solution

You can try a:

git fetch
git reset origin/master
git update-index --skip-worktree foo/*
git checkout --

The checkout should ignore the folder foo because of the git update-index command.

OTHER TIPS

Not sure this is the best way to do this, but I did it with this little hack:

The commit part is what I wrote in the question, the checkout is the tricky one:

$ git fetch
$ git checkout origin/master && \
git log HEAD^..HEAD --summary --diff-filter=D \
| grep delete | awk '{print $4}' | xargs git checkout HEAD^ -- \
&& git reset HEAD

This way I checkout the latest commit in master, checkout everything that was deleted in the latest commit and then reset to HEAD so the deleted & checked-out file would be unstaged.

It works, but I still would like to see some nicer way for this for the next time this happens.

Introduction:

The accepted answer seems like it would work in some cases, but didn't seem like a perfect fit for what I was trying to do, so here's another approach:

Backstory:

I'm trying to keep track of what files some software generates, and so I'm committing various things into a git repo that I don't ever intend to share, just to see what's there.

Some files are created that are labeled as temp. I want to capture them in git, but mostly, I want to ignore them, and not track changes regularly (but be able to, if I want to), so, I wanted to create a branch with-temp-files, check the files in there, but then not get rid of the files when switching back to my main branch, where I'd then add a .gitignore to ignore them while I'm on main.

The problem with the accepted answer (for me):

When doing the git reset, I was just going resetting to main -- there is no origin (or any other remote), so that didn't make sense. And I'm wanting to keep a branch that has the files, I just don't want them on my main branch.

My solution, for my situation:

  1. Starting from a worktree that's got these new files in it, but is otherwise pristine
  2. git add temp -- add the extra files
  3. git commit -- get them into the repo
  4. git branch with-temp-files -- now create a new branch on the commit that has the files added, but don't switch to it.
  5. git reset HEAD^ -- reset main to back before the new commit, leaving with-temp-files as its own branch. The working tree is left alone (the files are still there, now again in an untracked state).

A potentially more generalize-able answer:

  1. Assuming you have a tree that has these added files, but no other changes since adding them (if this is not your situation, then more care is needed; beyond the scope of this answer)
  2. Determine the commit that contains the unwanted files, let's pretend it's abc123
  3. Determine the commit that's prior to the unwanted files having been added, let's pretend it's def456 (though it could be indirectly referenced with something like origin/main).
  4. [optional, if you want to keep track of the branch] use either git branch with-files abc123 or git tag with-files abc123 (changing with-files to any name you desire)
  5. Run git reset def456 to go back to a state before the files were added. Without other arguments (e.g. --hard, which would remove things -- not what we want here), the reset should leave the new files in the worktree.

Hopefully this adds some additional insights for anyone else trying to work through similar situations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top