(It looks like they have a swearing-safe version now at https://dangitgit.com/)
# undo the last commit, but leave the changes available
git reset HEAD~ --soft
git stash
# move to the correct branch
git checkout name-of-the-correct-branch
git stash pop
git add . # or add individual files
git commit -m "your message here";
# now your changes are on the correct branch
Or you can use a powerful GUI like SmartGit. Then you don't have to memorize anything or look up a recipe. For the situation above, you simply drag your branch markers to where you want them in the log. Done!Similarly, for situations where you would look up hashes in the reflog, just click the Recyclable Commits checkbox, and everything in the reflog shows up as ordinary commits in the same commit tree as everything else. You can even see diffs between the reflog commits and your regular commits without having to do any temporary checkouts.
I know many developers like the command line and don't want to consider using a GUI. But I encourage you to give SmartGit a try. It works in conjunction with the command line, so you you're not locked into the GUI, you can use either one whenever you want.
Git reset changes the ref HEAD is pointing at. So in this case HEAD is pointing to the branch you've accidentally committed to. Running `git reset HEAD- --soft` simply moves the branch to point to one commit previous. The soft flag tells git reset to not touch any actual files while doing this, so your changes stay untouched. This is really the most complex part. After this all that's happening is re-committing the same changes to the correct branch. The git stash is even optional if the changes don't conflict with any changes done by the checkout.
You're right, memorizing a list of commands like that is a fools errand. What's not a fools errand is understanding the underlying data structure of git and how various commands act on it. Which is all documented in the official docs by the way, using a writing style that's rather readable in my opinion. Switching to a GUI wholesale is throwing out the baby with the bathwater. Using a GUI tool still requires knowing how git works to be effective.
Of course you might still argue that it's too much typing, which is probably true. Good thing git aliases got invented so even though I can recall the entire command list you mentioned from memory I'd still in practice simply run "git uncommit" since I've had that alias defined for about forever now.
This comment isn't aimed at anyone in particular and especially not at the parent comment. The parent comment just hit my grumpy button I think ;-)
A conceptually simple way (for me) is to: checkout "good" branch, cherry-pick the "wrong" commit, then checkout the "bad" branch and remove the "wrong" commit ("git reset --hard HEAD^").
Mixing and matching simple commands mechanistically means everything can in fact be remembered.
YMMV.
Do you know of git GUIs that explicitly maintain a bijection between the GUI and the underlying command history? It'd be cool to use the GUI and see the command history, or use the CLI and see updates in the GUI.
For me, I had trouble first using `git` after experience with `cvs` and `subversion`. At some point, everything clicked because I inferred its internal model.
Oh, and the fact that a ‘git checkout’ is an unrelated concept to ‘svn checkout’ - and how SVN branches are “spatial” compared to git’s “parallel-universes” model is also a source of confusion.
If I could go back in time to 2005 (in addition to getting in super early on bitcoin) I’d beg Linus to not reuse SVN terminology. Personally I’d go with “git switch” instead of checkout, and “timeline” or “line” for short instead of “branch”. The fact that git branches are not 1-connected graph routes is enough reason not to call them “branches”.
I’d also convince him to include a “gitd” mode that would automatically fetch from upstream and automatically add commits when it detects file-move/rename changes. (I understand why git doesn’t have an exact “rename” op, but tooling today still isn’t good enough to detect rename-then-edit or rename-then-split operations without an intermediate rename-only commit. My dream “gitd” would also make auto-commits every 30 seconds just to give me a powerful filesystem undo feature. If you had hours of work that resulted in new files before you staged them and you accidentally did a hard reset then you’re sol - and this has happened to me already :/
Also, if you’re in a panic because something went screwy, check “git status” and read every line carefully. status tells you a lot more than you might expect - what branch you’re on, if you’re even on a branch, what merge/rebase/commit operation you’re in the middle of (if any), and even how to go forward with or back out of the current operation.
Finally, commit regularly and often! reflog and rebase mean that you can always maintain a clean history if you want, while committing makes sure that your changes are properly tracked and saved by git so you can rewind when needed. Once you get comfortable with it, git lets you really practice fearless experimentation, which unlocked a whole new level of productivity for me.
Seconded, but I'd go even further. Run and read git status before and after running any git command until you get comfortable enough with git to where you can predict the output without running it.
Additionally you can go get git prompt[1] installed so you always know your git status at a glance. Saves a lot of typing in any case.
As a last suggestion I'd say go read git-scm.com[2]. It has the excellently written man pages for looking up what a command does and which flags it takes. It also has an amazingly written free ebook explaining git top-to-bottom. After reading that you'll be a git wizard compared to your peers.
[1] https://github.com/git/git/blob/master/contrib/completion/gi... [2] https://git-scm.com/
Unfortunately so many people put that aside and never read it, and then come back to me a few weeks later because they messed everything up again, and still do not understand what I mean with "index".
Git is very powerful but a bit awkward, so I consider knowing the underlying concepts necessary to use it properly.
https://git-man-page-generator.lokaltog.net/#4b16e11f044dd60...
There's beauty and elegance in the implementation details of git. You can do and undo with confidence once you can translate the changes you want to make to git object transformations.
To get an overview of the concepts behind git I recommend this article by one of the GitHub founders: http://tom.preston-werner.com/2009/05/19/the-git-parable.htm...
To understand the data structures I suggest: https://codewords.recurse.com/issues/two/git-from-the-inside...
I cannot agree with this more! The data structure makes git git, there are some questionable CLI design choices but they all melt away once you get the data structure.
In relation to trying to manipulate commits and "undoing things", everything will be significantly clearer the faster you can move away from thinking of undo like a one dimensional word processor function... Instead start to think of git as an immutable graph of commit objects you are able to traverse, reference and use in anyway - at that point "undo" seems like a completely inadequate description.
https://stackoverflow.com/questions/35115585/remove-file-fro...
git commit --amend
Doesn't automatically resign (or fail to resign if the key isn't available) a signed git commit message. Anytime there is a non-verified git commit message in my history you can be sure it's because I was a dummy on the original message.I’m bad at git. So... wait what now?
When is Master not Origin/Master? I don’t understand what is going on there. Explain?
git revert -m 1 88113a64a21bf8a51409ee2a1321442fd08db705I had a collision the other day on a mediums-sized when using a 6 character hash and was surprised. Git let me know and told me which objects collided.
Edit: Updated the link to go to the site referenced in the image. Might as well send you to who developed it so they get some credit.
Also Merry Christmas and Happy New Year.
Anyway, shouldn't git just come with a "undo" command?
Intellij has a "shelve" command, I decided to stick with "git stash". Magit has the "i", that does "ignore" but also cleans up already committed files, something like "git rm -r --cached ."