touch -- -l
ls * touch -- -l
ls -- *
The fact that you have to use a double-hyphen flag to create a file with a name starting with a hyphen is a strong indication that this situation is an edge case. rm master
git checkout -- master
git checkout a1b1
git checkout master -- master
all works as expectedYou'll note that, for example, your "rm" didn't require a double-hyphen.
The OC's point (and maybe the GP's point [1]), ultimately, is about git command syntax ambiguity. With traditional Unix commands, there's not much ambiguity. At worst, there's merely no obvious way to pass an argument that's a filename starting with a hyphen. The question "what does 'ls -l' do?" would not plausibly have an answer of "output '-l' if a directory entry with that name exists" in addition to "output a long listing of all directory entries".
[1] Does git actually behave differently based on the existence of a directory entry named "master" or does it merely require extra effort to work with such an entry, which would actually be directly analagous to filenames beginning with a hyphen?
* Checkout a file called a/b
* Checkout branch b from remote a
* Checkout a local branch called a/b
I've seen people end up with local branches with names like 'upstream/mybranch', then get super-confused about how these branches aren't "upstream". git should really ban local branches with a / in their name.
But the tool is not conceptually difficult. All the difficulty of git is in the trap its "UI" creates for no reason. The concepts are easy. I taught Darcs to a frontend/flash developer 15 years ago, and it's not because I'm a great teacher.
Conversely, attached HEAD means a branch is being updated whenever you make a commit, e.g. when you make commits on your local master.
When you move out of detached head state by checking out another branch Git tells you how to save your work to a branch.
It could very usefully try harder to avoid getting into that state in the first place.
That's a great idea and it really confuses me why they don't add obviously useful things to the interface.
Am I missing something here? How do you get into a detached HEAD state without explicitly taking an obviously weird action, like finding and checkout out a commit hash instead of a branch, and why would it make sense for git to not be in a detached HEAD state should you do that?
Most people don't think about doing a hard reset to the last good commit, and then soft resetting to HEAD~. Instead, they just "git checkout $LAST_GOOD_COMMIT". And afterwards they may even continue by working with a detached HEAD
Several times that I've helped junior developer out of a detached HEAD state, when I asked what they thought they were doing before it happened, the answer was "I was just doing my normal rebase before..."
But this isn't an obviously weird action? It happens all the time when you need to branch off from a previous point.
Maybe you're unexpectedly releasing a hotfix, maybe your current development is going in a bad direction, maybe you need to test something against a previous state.
I checked out master but now my commit is no longer there. HELP!
Can I somehow push my changes to you so you can fix it?
Ah let's intuitively try:
git log --graph --decorate $(git rev-list -g --all)
For comparisson:
- mercurial would show your commit all the time, no matter what currently is checked out.
- Only when you push, you have to force it, to create a new head in the remote repository because most workflows expect you to merge heads locally.
Detached is just that: you can party on it all you want, but it's not going to go anywhere when you commit unless you go out of your way.
Every digital damage can be undone by wasting enough time.