From 99edc9a6d32e7ee8add7bad97a5b9c8b6f53cdec Mon Sep 17 00:00:00 2001 From: Bhupesh-V Date: Fri, 23 Apr 2021 12:19:58 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9E=95=20reccover/undo=20accidental=20file?= =?UTF-8?q?=20delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ++++++++++++++++++++++- ugit | 24 +++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 572bd85..e1f2f40 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ - [ ] Undo `git tag` (rename a tag) - [ ] Undo `git rebase` - [ ] Undo `git cherry-pick` -- [ ] Undo accidental file delete (Restore a deleted file after a commit) +- [x] Undo accidental file delete (Restore a deleted file after a commit) - [ ] Undo `git worktree remove` (recover deleted work-tree) ## Installation @@ -65,6 +65,27 @@ curl -fsSL https://raw.githubusercontent.com/Bhupesh-V/ugit/master/ugit && chmod curl -fsSL https://raw.githubusercontent.com/Bhupesh-V/ugit/master/ugit && chmod +x ugit && mv ugit /usr/local/bin ``` +## Please read ⚠️ + +Git comes with a garbage collector ([in case you didn't know](https://git-scm.com/docs/git-gc)) therefore undoing some commands will become impossible if the entries are deleted from the reflog. +One way to prevent this is to increase default time limits before the reflog entries expire: +Add these configuration in your global `.gitconfig` file: + +```gitconfig +[gc] + # default 90 days + reflogExpire = 200 +``` +Used to set how long records in a branches reflog should be preserved. + +```gitconfig +[gc] + # default 30 days + reflogExpireUnreachable = 90 + +``` +Used to set how long inaccessible reflog records should be preserved. + ## Not satisfied? 😒️ You can read my in-process guide on [**How to undo anything in Git**](https://bhupesh.gitbook.io/notes/git/how-to-undo-anything-in-git) diff --git a/ugit b/ugit index 7e41ea9..5bbef80 100755 --- a/ugit +++ b/ugit @@ -1,6 +1,7 @@ #!/usr/bin/env bash # ugit: Undo your last oopsie in Git +# Read the guide: https://bhupesh.gitbook.io/notes/git/how-to-undo-anything-in-git # TODO: Add self-updating --update # @@ -42,6 +43,8 @@ display_menu() { printf "%s\n" "Undo [git stash apply]" printf "%s\n" "Undo [git tag -d] tag delete" printf "%s\n" "Undo [git rebase]" + printf "%s\n" "Undo/Recover commited file delete" + printf "%s\n" "Undo/Recover uncommited file delete" } option=$(display_menu | nl -n ln | fzf --header="Don't worry we all mess up sometimes" --height 30% --reverse --pointer='ᐅ' --cycle | awk '{print $1}') @@ -141,10 +144,8 @@ undo_git_stash_apply() { recover_deleted_tag() { # only works for annotated tags? :( + printf "%s" "Note: Only annotated tags can be restored" - # git fsck --unreachable | grep tag - # to see changes git show - # git update-ref refs/tags/ read -p "Enter lost Tag name (e.g v1.2): " -r TAG_NAME COMMIT_HASH=$(git fsck --no-progress --unreachable --tags | awk '/tagged/ {print $6}') [[ -z "$COMMIT_HASH" ]] && printf "%s\n" "Unable to find any deleted tags :(" && exit 1 @@ -161,6 +162,21 @@ recover_deleted_tag() { fi } +undo_file_delete() { + if [[ "$1" == "uncommited" ]]; then + DELETED_FILE=$(git ls-files -d | fzf --ansi --height 20% --reverse --header="Choose deleted file to recover" | awk '{print $1}') + if git checkout HEAD "$DELETED_FILE"; then + printf "%s\n" "$DELETED_FILE Successfully Recovered" + exit 0 + fi + fi + commit_hash=$(git log --diff-filter=D --oneline| fzf --ansi --height 20% --reverse --header="Choose commit that deleted the file" | awk '{print $1}') + read -p "Enter complete filename: " -r FILENAME + if git checkout "$commit_hash"~1 -- "$FILENAME"; then + printf "%s\n" "$FILENAME Successfully Recovered" + fi +} + case $option in 1) undo_git_commit;; 2) undo_git_push;; @@ -176,4 +192,6 @@ case $option in 12) undo_git_stash_apply;; 13) recover_deleted_tag;; 14) do_git_reset "Choose commit just before rebase started";; + 15) undo_file_delete;; + 16) undo_file_delete "uncommited";; esac