ruby-on-railsrubygitgitignoregit-clean

git clean deletes files in gitignore, db/production.sqlite3 is lost


I was trying to remove an untracked file from a branch that I deleted, and instead I accidentally deleted untracked and tracked files... including apparently the dev and production databases!!!

What should I do? git clone and start over from last commit?

Thomass-MacBook-Pro:livebytransit tomb$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    app/assets/javascripts/.txt
    app/assets/javascripts/shared/

nothing added to commit but untracked files present (use "git add" to track)
Thomass-MacBook-Pro:livebytransit tomb$ git clean -n
Would remove app/assets/javascripts/.txt
Thomass-MacBook-Pro:livebytransit tomb$ git clean -fx
Removing app/assets/javascripts/.txt
Removing db/development.sqlite3
Removing db/production.sqlite3
Removing log/development.log
Removing log/production.log

Solution

  • First off, git clean can only delete untracked files. It can not delete a tracked file (even if you've just done a git add on a file, it becomes untouchable by git clean). Any untracked files, by definition, are not recoverable by git since git just doesn't know about them. In case you had them tracked previously, you could check out a past version of the file.

    Secondly, The 2 commands you ran are not identical: the -x flag instructs git to remove all untracked files (even those ignored by various .gitignores). This is what has caused your problem.

    While your first command (git clean -n) showed you files it would clean ignoring the ones specified by gitignore rules, the second one(git clean -fx) included those as well for deletion due to the -x flag. As such, all untracked files are deleted - whether ignored by gitignore or not.

    In future, you should execute: git clean -f only, if you want the desired behaviour.

    For now, you should get hold of the db/*.sqlite files from a backup/some other developer/via database migrations if needed. The *.log files should hopefully get automagically generated by your dev setup, if not, just create empty files with the name.

    Quoting from the documentation:

    $ man git-clean

    Cleans the working tree by recursively removing files that are not under version control, starting from the current directory.

    -x

    Don’t use the standard ignore rules read from .gitignore (per directory) and $GIT_DIR/info/exclude, but do still use the ignore rules given with -e options. This allows removing all untracked files, including build products.

    -n, --dry-run

    Don’t actually remove anything, just show what would be done.

    -f, --force

    If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f, -n or -i