Start here
What changed since the last commit
git status -sbSave the current state
git add -A then git commit -mUndo a change you have not committed
git restore script.ps1Undo a change already pushed
git revert <commit>Who wrote this line and when
git blame script.ps1I think I lost work
git reflog
This sheet is for infrastructure, not for shipping software. The point is that a script which broke production last Tuesday can be compared, explained and rolled back in one command, and that nobody has to guess which copy of
backup-final-v3.ps1 is the real one.
One-time setup on a Windows machine
| Task | Command |
|---|---|
| Identity on every commit | git config --global user.name "Zaur B" |
| Address, matched to your account | git config --global user.email you@example.com |
| Store credentials properly | git config --global credential.helper manager |
| Default branch name | git config --global init.defaultBranch main |
| Stop the divergent-branch prompt | git config --global pull.rebase true |
| Corporate proxy | git config --global http.proxy http://proxy:8080 |
| Paths longer than 260 characters | git config --global core.longpaths true |
| Ignore the Unix permission bit | git config --global core.fileMode false |
| See everything that is set, and where | git config --list --show-origin |
Putting a folder under version control
| Task | Command |
|---|---|
| Start a repo in an existing script folder | git init |
| First commit | git add -A then git commit -m "Initial import" |
| Attach it to GitHub | git remote add origin https://github.com/user/repo.git |
| Push and set tracking | git push -u origin main |
| Copy an existing repo | git clone https://github.com/user/repo.git |
| Clone only the latest state | git clone --depth 1 URL |
| Where is this repo pointing | git remote -v |
| Change the remote | git remote set-url origin NEW_URL |
A repo works without a server.
git init in C:\Scripts already gives you history, diffs and rollback. GitHub adds backup, review and sharing, and can come later.
The daily loop
| Task | Command |
|---|---|
| What is changed, in short form | git status -sb |
| What exactly changed in the file | git diff |
| What is about to be committed | git diff --staged |
| Stage everything, deletions included | git add -A |
| Stage one file | git add scripts\backup.ps1 |
| Commit | git commit -m "Fix retry count in backup job" |
| Amend the message you just wrote | git commit --amend |
| Send it | git push |
| Get other people’s work | git pull |
| Last ten commits, one line each | git log --oneline -10 |
Write the why, not the what. The diff already shows what changed. “Fix retry count in backup job” is worth something at 2 a.m. six months from now; “update” is not.
Undo, in order of violence
| Situation | Command |
|---|---|
| Discard edits to one file | git restore script.ps1 |
| Unstage a file, keep the edits | git restore --staged script.ps1 |
| Park changes to deal with something urgent | git stash then git stash pop |
| Undo the last commit, keep the changes staged | git reset --soft HEAD~1 |
| Undo the last commit, keep the files | git reset HEAD~1 |
| Undo the last commit and the files with it | git reset --hard HEAD~1 |
| Reverse a commit that is already pushed | git revert <commit> |
| Get one file back as it was in a commit | git restore --source <commit> -- script.ps1 |
| Find a commit you thought was gone | git reflog |
| Go back to what reflog showed | git reset --hard HEAD@{3} |
reset –hard is the one that bites. It throws away uncommitted work with no prompt and no recycle bin. Commit or stash first: a commit can always be undone, an overwritten working file cannot.
revert on anything shared.
reset rewrites history, which breaks every other clone. revert adds a new commit that undoes the old one, which is safe on a branch other people pull.
Branches
| Task | Command |
|---|---|
| New branch for a risky change | git switch -c fix-backup-retry |
| Move between branches | git switch main |
| List branches, local and remote | git branch -a |
| Bring the work back into main | git switch main then git merge fix-backup-retry |
| Delete a merged branch | git branch -d fix-backup-retry |
| Push a branch for review | git push -u origin fix-backup-retry |
| Drop remote branches that no longer exist | git fetch --prune |
One branch is a valid strategy. For a personal script repo, committing straight to
main is fine. Branches start paying for themselves when someone else reviews the change, or when you need to test a rewrite while the old version still runs.
Reading history
| Question | Command |
|---|---|
| What happened recently | git log --oneline --graph --decorate -20 |
| Everything that touched one file | git log --oneline -- scripts\backup.ps1 |
| The actual changes to that file over time | git log -p -- scripts\backup.ps1 |
| One commit in full | git show <commit> |
| Difference between two points | git diff HEAD~5 HEAD |
| Who last touched each line | git blame scripts\backup.ps1 |
| Find the commit that introduced a string | git log -S "Start-Job" --oneline |
| What changed between two releases | git log --oneline v1.2..v1.3 |
| Mark a known-good state | git tag -a v1.3 -m "Before the October change window" |
| Publish tags | git push --tags |
Tag before a change window. A tag turns “restore the scripts to how they were on Friday” into
git restore --source v1.3 -- ., which is one command and no argument about which backup is correct. Use git switch --detach v1.3 only to look, never to work: it leaves you off the branch, and anything you commit there is orphaned.
Secrets and what never goes in
| Task | Command or entry |
|---|---|
| Ignore secrets and noise | .gitignore with *.pfx, *.key, .env, *secret*, *.log |
| Stop tracking a file already committed | git rm --cached config\creds.ps1 |
| Check what is actually tracked | git ls-files |
| Test a pattern before trusting it | git check-ignore -v config\creds.ps1 |
| Search history for a leaked string | git log -S "Password" --oneline |
| Keep a template instead of the real file | commit config.sample.ps1, ignore config.ps1 |
A committed secret is a burned secret. Rewriting history does not un-clone it, and on GitHub it does not un-index it. Rotate the credential first, then clean the repository. In that order, every time.
Windows specifics
| Problem | Fix |
|---|---|
| Every file shows as modified after a clone | Line endings. Set core.autocrlf and commit a .gitattributes. |
| Normalise text files across platforms | * text=auto in .gitattributes |
| Keep CRLF in PowerShell and batch files | *.ps1 text eol=crlf and *.cmd text eol=crlf |
| Files that must ship byte for byte | * -text, which disables all conversion |
| Filename too long | git config --global core.longpaths true |
| Permission churn on every file | git config --global core.fileMode false |
| Authentication keeps failing | Use Git Credential Manager and a token, not an account password |
| Repo is huge and slow | Binaries do not belong in git. Keep installers and images out. |
Decide line endings once, in the repository. A
.gitattributes file travels with the repo and applies to everyone. A local core.autocrlf applies only to your machine, which is why the same file keeps flip-flopping between two admins.
GitHub from the command line
| Task | Command |
|---|---|
| Sign in once | gh auth login |
| Create a repo from the current folder | gh repo create --source . --private --push |
| Clone by name | gh repo clone user/repo |
| Open a pull request | gh pr create --fill |
| Review what is waiting | gh pr list |
| Publish a release | gh release create v1.3 --notes "October change window" |
| Check a workflow run | gh run list |
Private by default. For infrastructure scripts, create the repository private and make it public deliberately, never the other way round. Non-interactively,
gh repo create refuses to run without one of --private, --public or --internal, so always pass --private explicitly in a script.
FAQ
Do I need GitHub at all?
No. Git is local and complete on its own, and a repo in
C:\Scripts gives you history and rollback with no account anywhere. A remote adds off-machine backup and a second pair of eyes, which is why most script folders end up with one eventually.
git pull refuses to run and talks about divergent branches.
Git wants to know whether to merge or rebase. Set it once with
git config --global pull.rebase true, which keeps a script repo’s history linear and readable.
My password stopped working when pushing.
GitHub has not accepted account passwords over HTTPS for years. Use Git Credential Manager, which stores a token in Windows Credential Manager, or a personal access token entered in place of the password.
Can I version the configuration on a server without a network?
Yes.
git init in the config folder, commit before every change window, and you have a diff and a rollback path that does not depend on anything outside the box. Push it somewhere later if the machine ever gets a route out.
Someone force-pushed and my clone is broken.
Your commits still exist locally.
git reflog shows where you were, and you can branch from that point, then reconcile deliberately. This is the reason push --force is a conversation, not a reflex.