A git repository is best thought of as a sort of tree, where the nodes can potentially have multiple parents. This technically makes them a graph ("directed acyclic" to show I do know the technical terms), but our human intuition will mostly work thinking of them as a tree. To understand multiple parents use your intuition about human beings, since we all have multiple parents.
A "branch" doesn't really have any special status in git. All it is is a pointer to a particular commit. Literally, that is all it is, even in the data structures. It has no additional ontological existence beyond that. When you make a commit to a "branch", all that happens is that git moves the branch marker along to the next commit. All of the "specialness" of a branch is what is in that behavior.
You can do anything you want with that branch marker, such as yanking it to a completely different part of the tree via "git reset --hard $NEW_COMMIT", and while you may confuse humans, you haven't confused git in the slightest. On the flip side, since branches don't actually "exist", it is perfectly sensible to "merge" with a direct commit hash, because that's all a branch is; a pointer to a hash. You can pick up that pointer and drop it down where ever you want.
(A tag is the same thing as a branch, except that when you're "on" a tag and make a commit to it, git does not advance the tag. But almost all it is is a pointer to a commit. Technically it can carry a bit more data, like a signature, but as far as the core structure is concerned it's just a commit.)
I am not the original poster, but I have a training I give at work for git, and it is heavily based on making sure this understanding is presented. (The other reason I wrote my own training rather than reusing any of the many other existing ones is mine makes sure to walk the trainees through the confusing states you can get into, then we explain what happened, why, and how to correctly get out of them. They follow along as we all manipulate a repository, and the training actually spends quite a bit of time in a "detached head" state, checking out, merging, and resetting to commits directly.)
>> makes sure to walk the trainees through the confusing states you can get into,
>> then we explain what happened, why, and how to correctly get out of them
- you don't where somewhere and you moved and you can't go back: "git reflog"
- local repo and remote with a different history (e.g: you rebased on a published branch): the whole team to sync with remote except you, then hold. Export your remaining changes as a patch. Reclone. Apply patch.
- remote has a different history than the rest of the team (e.g: you forced push a different history): Delete remote, recreate, repush from one of the team mate, then apply previous solution.
- your messed up your merge and wish to never have done that: "git reset --merge"
- the last commit is not published and you messed it up: "git commit --amend"
- the last commit is published and you messed it up: "git revert HEAD"
But rather than solve problems, better not get them in the first place. Always "git status" before anything, always get a clean working copy before checkout/pull, create a fat gitignore, etc.
Not meaningfully. It isn't written as a blog post document; it's a series of commands and presentation notes, designed to be delivered live by me. You can basically obtain what I have in the document by combining A: what I wrote above B: a good git tutorial, see internet and C: some screwing around with using git checkout, reset, and merge with commit hashes directly on a little repo you use locally.
A "branch" doesn't really have any special status in git. All it is is a pointer to a particular commit. Literally, that is all it is, even in the data structures. It has no additional ontological existence beyond that. When you make a commit to a "branch", all that happens is that git moves the branch marker along to the next commit. All of the "specialness" of a branch is what is in that behavior.
You can do anything you want with that branch marker, such as yanking it to a completely different part of the tree via "git reset --hard $NEW_COMMIT", and while you may confuse humans, you haven't confused git in the slightest. On the flip side, since branches don't actually "exist", it is perfectly sensible to "merge" with a direct commit hash, because that's all a branch is; a pointer to a hash. You can pick up that pointer and drop it down where ever you want.
(A tag is the same thing as a branch, except that when you're "on" a tag and make a commit to it, git does not advance the tag. But almost all it is is a pointer to a commit. Technically it can carry a bit more data, like a signature, but as far as the core structure is concerned it's just a commit.)
I am not the original poster, but I have a training I give at work for git, and it is heavily based on making sure this understanding is presented. (The other reason I wrote my own training rather than reusing any of the many other existing ones is mine makes sure to walk the trainees through the confusing states you can get into, then we explain what happened, why, and how to correctly get out of them. They follow along as we all manipulate a repository, and the training actually spends quite a bit of time in a "detached head" state, checking out, merging, and resetting to commits directly.)