Question: Is there a single command that will print the current branch (e.g. `master`) if there is one, or the commit hash if it is detached? The purpose is to give me something to write down so I can later execute `git switch <branch_or_commit>` to get back to where I started.

This is to be used programmatically, so no scraping of `git status`, Bash pipes or whatever. The answer needs to use the "plumbing" commands, which have guarantees about the format and stability of their output.

Also I should note that there are many many questions asking for each of these thinks individually, but not together. **PLEASE THINK BEFORE CASUALLY MARKING THIS AS A DUPLICATE.**

Here are the things I have tried. The closest is actually `cat .git/HEAD`.

| Command | Output on a branch | Output when detached |
| --- | --- | --- |
| `git rev-parse HEAD` | `cedbe9...` | `cedbe9...` |
| `git rev-parse --abbrev-ref HEAD` | `master` | `HEAD` |
| `git symbolic-ref --short HEAD` | `master` | `fatal: ref HEAD is not a symbolic ref` |
| `cat .git/HEAD` | `ref: refs/heads/master` | `cedbe9...` |
| `git branch --show-current` | `master` | (no output) |
| your answer here | `master` | `cedbe9...` |

Answer: 
Impossible with exactly one command but possible with two:

```
git symbolic-ref -q --short HEAD || git rev-parse HEAD

```

Get the current branch; but if detached get the hash.
> 
> The purpose is to give me something to write down so I can later execute `git switch <branch_or_commit>` to get back to where I started.
> 
> 
> 

You'll need to know whether the thing-you-got-back is a *branch name* or a *commit hash ID* because `git switch` demands the `--detach` flag when using a hash ID, but using `--detach` with a branch name will produce the wrong result.

Thus, you *need* to know whether you're getting a symbolic name:

```
if switchname=$(git symbolic-ref -q --short HEAD); then
    detach=
else
    switchname=$(git rev-parse HEAD) || exit  # quit if unborn branch
    detach="--detach"
fi

```

and later:

```
git switch $detach $switchname

```

for instance.

There's a flaw in the above: if you *are* on an unborn branch, `git symbolic-ref -q --short HEAD` will produce the branch name, but `git switch` won't be able to switch *to* it. It's probably wise to run both `git symbolic-ref` *and* `git rev-parse HEAD` so as to detect the unborn branch case.