{"id":15007949,"url":"https://github.com/ni554n/git-local-backup","last_synced_at":"2026-03-10T17:34:31.868Z","repository":{"id":257671938,"uuid":"859041090","full_name":"ni554n/git-local-backup","owner":"ni554n","description":"CLI tool to backup local files that are not pushed to the remote (yet)","archived":false,"fork":false,"pushed_at":"2025-02-28T23:38:41.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-01T00:36:06.473Z","etag":null,"topics":["automation","backup","cli","git","git-tool","go"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ni554n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-18T01:19:58.000Z","updated_at":"2025-02-28T23:37:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"6d10f4fc-b451-4bd8-a4d9-d149b3a92307","html_url":"https://github.com/ni554n/git-local-backup","commit_stats":null,"previous_names":["ni554n/git-local-backup"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ni554n%2Fgit-local-backup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ni554n%2Fgit-local-backup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ni554n%2Fgit-local-backup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ni554n%2Fgit-local-backup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ni554n","download_url":"https://codeload.github.com/ni554n/git-local-backup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243180486,"owners_count":20249295,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","backup","cli","git","git-tool","go"],"created_at":"2024-09-24T19:14:36.058Z","updated_at":"2025-12-11T17:02:44.972Z","avatar_url":"https://github.com/ni554n.png","language":"Go","readme":"# Git Local Backup\n\nA CLI tool for copying local files from Git projects to a cloud drive or a backup disk for safekeeping.\n\n```\n- Projects                           - Backup\n  - project-1                --\u003e       - project-1\n    - .git                               - main.go\n    - main.go [modified]\n    - utils.go [deleted]\n    - README.md [origin]\n  - project-2                --\u003e       - project-2\n    - .git                               - .env\n    - .gitignore                         - index.js\n    - .env [forced]                      - README.md\n    - index.js [untracked]\n    - package.json [origin]\n    - README.md [added]\n```\n\nIt copies only the files that have been modified since the last backup, including:\n\n- Committed files that are not yet pushed to the remote repository\n- Working and staged files that are not yet committed\n- Files that are not yet tracked by `git add`\n- Any .gitignored file included via `--force-include` flag\n\n\u003e … basically every unpushed file that can be lost during an incident.\n\n## Why?\n\nMost modern editors now have built-in local history feature, so pushing unfinished changes solely\nfor backup purposes seems counter-productive to me.\nTo reduce the risk of accidental data loss in between remote pushing,\nthis tool can provide a layer of protection.\n\nPlus, there's a lot of important files that cannot be committed to VCS,\nsuch as `.env` containing private keys that should be backed up locally with a tool like this.\n\n## Prerequisites\n\n- Git is installed and added to the `PATH` so that it's accessible from anywhere\n- Have some sort of a backup solution in place\n- Optionally, subscribe to update notifications by selecting `Watch \u003e Custom \u003e Releases` on GitHub\n\n## Usage\n\nDownload the [latest release](https://github.com/ni554n/git-local-backup/releases/latest) and\nextract (`tar -xvzf`) the binary to a suitable path.\n\nHere's all the options you can configure:\n\n| Flag | Description |\n| --- | --- |\n| `--projects-path` | Path to the projects directory (required) |\n| `--backup-path` | Path to an empty backup directory (required)\u003cbr\u003eOtherwise, existing files may be removed from that directory. |\n| `--remote-branch` | Remote name (default: `origin`) |\n| `--force-include` | Always include a git ignored file or directory like `.git`.\u003cbr\u003eSpecify it multiple times to include multiple items. |\n| `--dry-run` | Preview changes without modifying the backup directory |\n\n### Test drive the command\n\nAssuming all your Git projects are in `~/Projects` and you want to backup to `~/OneDrive/Backup/Projects`:\n\n```sh\n/path/to/git-local-backup --projects-path \"~/Projects\" --backup-path \"~/OneDrive/Backup/Projects\" --dry-run\n```\n\nIf you also want to back up Git internals like stashes, or other gitignored files such as `.env`:\n\n```sh\n/path/to/git-local-backup --projects-path \"~/Projects\" --backup-path \"~/OneDrive/Backup/Projects\" --force-include \".git\" --force-include \".env\" --dry-run\n```\n\nIf you are satisfied with the output, remove the `--dry-run` flag, and\nschedule the command to run periodically using the instructions below.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003eLinux (Crontab)\u003c/h3\u003e\u003c/summary\u003e\n\nRun `crontab -e` and add the following line:\n\n```txt\n*/15 * * * * /path/to/git-local-backup \"~/Projects\" --backup-path \"~/OneDrive/Backup/Projects\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003eMacOS (Launchd)\u003c/h3\u003e\u003c/summary\u003e\n\n1. Create this plist file in the `~/Library/LaunchAgents/` and configure it your command:\n\n`git-local-backup.plist`\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n  \u003ckey\u003eLabel\u003c/key\u003e\n  \u003cstring\u003eGit Local Backup\u003c/string\u003e\n  \u003ckey\u003eProgramArguments\u003c/key\u003e\n  \u003carray\u003e\n    \u003cstring\u003e/path/to/git-local-backup --projects-path \"~/Projects\" --backup-path \"~/OneDrive/Backup/Projects\"\u003c/string\u003e\n  \u003c/array\u003e\n  \u003ckey\u003eStartInterval\u003c/key\u003e\n  \u003cinteger\u003e900\u003c/integer\u003e \u003c!-- 900 seconds = 15 minutes --\u003e\n  \u003ckey\u003eRunAtLoad\u003c/key\u003e\n  \u003ctrue/\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\n```\n\n2. Load it via `launchctl load ~/Library/LaunchAgents/git-local-backup.plist`\n3. Start it via `launchctl start git-local-backup`\n4. Check the status via `launchctl list | grep git-local-backup`. A status of zero means a successful run.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003eWindows (Task Scheduler)\u003c/h3\u003e\u003c/summary\u003e\n\n1. Create the following file and configure it with your command. You can also modify it later during import.\n\n`Git Local Backup.xml`\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-16\"?\u003e\n\u003cTask version=\"1.4\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\"\u003e\n  \u003cRegistrationInfo\u003e\n    \u003cAuthor\u003eni554n\u003c/Author\u003e\n    \u003cDescription\u003ehttps://github.com/ni554n/git-local-backup\u003c/Description\u003e\n    \u003cURI\u003e\\ni554n\\Git Local Backup\u003c/URI\u003e\n  \u003c/RegistrationInfo\u003e\n  \u003cTriggers\u003e\n    \u003cLogonTrigger\u003e\n      \u003cRepetition\u003e\n        \u003cInterval\u003ePT15M\u003c/Interval\u003e \u003c!-- 15 minutes --\u003e\n        \u003cStopAtDurationEnd\u003efalse\u003c/StopAtDurationEnd\u003e\n      \u003c/Repetition\u003e\n      \u003cEnabled\u003etrue\u003c/Enabled\u003e\n    \u003c/LogonTrigger\u003e\n  \u003c/Triggers\u003e\n  \u003cPrincipals\u003e\n    \u003cPrincipal id=\"Author\"\u003e\n      \u003cLogonType\u003eS4U\u003c/LogonType\u003e\n      \u003cRunLevel\u003eLeastPrivilege\u003c/RunLevel\u003e\n    \u003c/Principal\u003e\n  \u003c/Principals\u003e\n  \u003cSettings\u003e\n    \u003cMultipleInstancesPolicy\u003eStopExisting\u003c/MultipleInstancesPolicy\u003e\n    \u003cDisallowStartIfOnBatteries\u003efalse\u003c/DisallowStartIfOnBatteries\u003e\n    \u003cStopIfGoingOnBatteries\u003etrue\u003c/StopIfGoingOnBatteries\u003e\n    \u003cAllowHardTerminate\u003etrue\u003c/AllowHardTerminate\u003e\n    \u003cStartWhenAvailable\u003efalse\u003c/StartWhenAvailable\u003e\n    \u003cRunOnlyIfNetworkAvailable\u003efalse\u003c/RunOnlyIfNetworkAvailable\u003e\n    \u003cIdleSettings\u003e\n      \u003cStopOnIdleEnd\u003etrue\u003c/StopOnIdleEnd\u003e\n      \u003cRestartOnIdle\u003efalse\u003c/RestartOnIdle\u003e\n    \u003c/IdleSettings\u003e\n    \u003cAllowStartOnDemand\u003etrue\u003c/AllowStartOnDemand\u003e\n    \u003cEnabled\u003etrue\u003c/Enabled\u003e\n    \u003cHidden\u003efalse\u003c/Hidden\u003e\n    \u003cRunOnlyIfIdle\u003efalse\u003c/RunOnlyIfIdle\u003e\n    \u003cDisallowStartOnRemoteAppSession\u003efalse\u003c/DisallowStartOnRemoteAppSession\u003e\n    \u003cUseUnifiedSchedulingEngine\u003etrue\u003c/UseUnifiedSchedulingEngine\u003e\n    \u003cWakeToRun\u003efalse\u003c/WakeToRun\u003e\n    \u003cExecutionTimeLimit\u003ePT0S\u003c/ExecutionTimeLimit\u003e\n    \u003cPriority\u003e7\u003c/Priority\u003e\n  \u003c/Settings\u003e\n  \u003cActions Context=\"Author\"\u003e\n    \u003cExec\u003e\n      \u003cCommand\u003e\\path\\to\\the\\git-local-backup.exe\u003c/Command\u003e \u003c!-- Replace with your executable path --\u003e\n      \u003cArguments\u003e--projects-dir \"~/Projects\" --backup-dir \"~/OneDrive/Backup/Projects\"\u003c/Arguments\u003e\n    \u003c/Exec\u003e\n  \u003c/Actions\u003e\n\u003c/Task\u003e\n```\n\n2. Open `Task Scheduler` and import this task via `Action \u003e Import Task` from the top menu bar\n3. Check both `Run whether user is logged on or not` and `Do not store password` option.\nOtherwise, a terminal window will pop up on each run.\n4. To test it, manually run the task from `ni554n` folder\n5. Refresh the task list and check the `Last Run Result` column to see if it's a successful run\n\n\u003c/details\u003e\n\n## Information\n\n**Author:** [Nissan Ahmed](https://anissan.com) ([@ni554n](https://twitter.com/ni554n))\n\n**Donate:** [PayPal](https://paypal.me/ni554n)\n\u003cimg src=\"https://ping.anissan.com/?repo=git-local-backup\" width=\"0\" height=\"0\" align=\"right\"\u003e\n","funding_links":["https://paypal.me/ni554n"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fni554n%2Fgit-local-backup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fni554n%2Fgit-local-backup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fni554n%2Fgit-local-backup/lists"}