# Git - Miscellaneous
Assorted tips and commands.
## Switch to Previous Branch
Like [[Bash and Zsh#Directory Stack (`cd -`, `pushd`, `popd`)|cd -]] for directories, git can jump back to previous branches.
Git records every branch switch in the reflog. List recent switches with:
```bash
git reflog | grep 'checkout:'
```
You can reference the Nth previous branch using the `@{-N}` syntax — it works anywhere git accepts a revision (`switch`, `checkout`, `merge`, `rebase`, `log`, etc.):
| Command | Meaning |
|---------|---------|
| `git switch -` | Previous branch (shorthand for `@{-1}`) |
| `git switch @{-2}` | 2 checkouts ago |
| `git switch @{-N}` | N checkouts ago |
| `git checkout -` | Same as `git switch -` |
| `git checkout @{-N}` | Same as `git switch @{-N}` |
`@{-N}` works anywhere git accepts a revision — `merge`, `rebase`, `log`, etc. Note: `git checkout -2` does **not** work — the full `@{-N}` form is required for N > 1.
## Cherry-Pick Commits onto a New Branch
Quick workflow for taking existing commits and opening a PR from a clean branch:
```bash
git checkout -b fix/thing master # new branch from master
git cherry-pick <sha1> <sha2> # pick the commits
git checkout - # back to where you were
```
If you have unstaged changes, stash first (`gsta`) or commit them before branching.
## Remove (remote) branch locally
[source](https://stackoverflow.com/questions/28258679/how-to-remove-a-branch-locally)
```bash
git branch -d -r origin/master
```
And to remove all:
[source](https://stackoverflow.com/questions/41350191/delete-all-remote-tracking-branches-for-a-remote-git-repository/41576929#41576929)
```bash
git branch -rd $( git branch -r | grep 'wr/' )
```
## Manage file permissions on Windows
[source](https://stackoverflow.com/questions/6476513/git-file-permissions-on-windows#13593391)
`git update-index --chmod=+x <file>`
## List all files in a commit
[source](https://stackoverflow.com/questions/424071/how-do-i-list-all-the-files-in-a-commit)
How can I print a plain list of all files that were part of a given commit?
Although the following lists the files, it also includes unwanted diff information for each:
```bash
git show a303aa90779efdd2f6b9d90693e2cbbbe4613c1d
```
> I'll just assume that [`gitk`](https://git-scm.com/docs/gitk) is not desired for this. In that case, try `git show --name-only <sha>`.
>
> — [SO answer](https://stackoverflow.com/questions/424071/how-do-i-list-all-the-files-in-a-commit)
## `HEAD~<n>` vs `HEAD^<n>`
[source](https://stackoverflow.com/a/2222920/4700312)
### Rules of thumb
- Use `~` most of the time — to go back a number of generations, usually what you want
- Use `^` on merge commits — because they have two or more (immediate) parents
Mnemonics:
- Tilde `~` is almost linear in appearance and wants to go backward in a straight line
- Caret `^` suggests an interesting segment of a tree or a fork in the road
## Who is "us" and who is "them"?
[source](https://stackoverflow.com/questions/21025314/who-is-us-and-who-is-them-according-to-git)
## Permissions for 'private-key' are too open
SSH refuses to use a private key if other users can read it. Keys must only be accessible to the user they're intended for and no other account, service, or group.
**macOS/Linux:**
```bash
chmod 600 ~/.ssh/id_rsa
```
**Windows GUI:**
File Properties → Security → Advanced
- Owner: Change → Select a principal → Enter key's user → OK
- Permission Entries: Remove all except for the key's user
- Set key's user to Full Control if not already set
**Windows CMD:**
```cmd
Set Key="%UserProfile%\.ssh\id_rsa"
:: Remove Inheritance:
Icacls %Key% /c /t /Inheritance:d
:: Set Ownership to Owner:
:: Key's within %UserProfile%:
Icacls %Key% /c /t /Grant %UserName%:F
:: Key's outside of %UserProfile%:
TakeOwn /F %Key%
Icacls %Key% /c /t /Grant:r %UserName%:F
:: Remove All Users, except for Owner:
Icacls %Key% /c /t /Remove:g "Authenticated Users" BUILTIN\Administrators BUILTIN Everyone System Users
:: Verify:
Icacls %Key%
set "Key="
```
**PowerShell:**
```powershell
New-Variable -Name Key -Value "$env:UserProfile\.ssh\id_rsa"
# Remove Inheritance:
Icacls $Key /c /t /Inheritance:d
# Set Ownership to Owner:
# Key's within $env:UserProfile:
Icacls $Key /c /t /Grant ${env:UserName}:F
# Key's outside of $env:UserProfile:
TakeOwn /F $Key
Icacls $Key /c /t /Grant:r ${env:UserName}:F
# Remove All Users, except for Owner:
Icacls $Key /c /t /Remove:g Administrator "Authenticated Users" BUILTIN\Administrators BUILTIN Everyone System Users
# Verify:
Icacls $Key
Remove-Variable -Name Key
```
([source](https://superuser.com/a/1329702/744283))