I’m a git noob.
I was panicking as usual because I accidentally committed my changes on to the master branch. We’re supposed to just git checkout
and create a new branch, opening a pull request before merging to master.
So i was furiously googling, and this came up:
git reset —soft
git checkout - How to revert a Git repository to a previous commit - Stack Overflow
git reset --soft <commit>
- Revert back while keeping the changes.
- Does not change the working tree.
- Goes back to commit status such as unstage files.
I tried using git reset --soft HEAD^
. I’m still not sure what’s the difference between HEAD^ and HEAD. Apparently:
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
Source: What’s the difference between HEAD^ and HEAD~ in Git? - Stack Overflow
So it worked, my changes got unstaged. But when i switched to a new branch, it seemed to have disappeared?? So i was panicking because usually i use git status
and git log
to check for modified files, staged / unstaged etc. I was so scared that all my code went missing.
git reflog
Thankfully, after googling, i found this command: git reflog
— Recovering a git reset —soft - Stack Overflow — which logs out commits that are not in my working tree anymore. Lo and behold, my commits are still there. Phew, all i have to do is to just reset back to that commit and make sure to push it up now.
Kinda weird why git log
doesn’t show the commits.
Top comments (14)
i havent tried gitkraken, is it better than sourcetree? been using sourcetree but since a few mths back, i've switched to just terminal. now i just use
git log --graph --oneline --decorate
to see the structure hahaI added the following to my global git config, it's a pretty compact git flow IMO.
I was Terminal-only for a while too. But for a simple GUI that speeds up your most common operations, I have to recommend GitKraken.
I still hang onto my terminal for when I need it though. GitKraken doesn't cover everything that, say, SourceTree does, but its GUI is much cleaner and I'm already comfortable enough in a terminal that I'm fine doing the more advanced stuff that way.
As an aside, I'd recommend being comfortable with git CLI anyway. Trying to learn with a GUI alone tends to hide a lot of the important stuff.
What left me wondering is why the master wasn't protected!?
Anyway, git-revert is super helpful in such incidences, it mutates the branch history though. But it makes sure you don't lose your changes under any incident. If you feel like you lost your changes, you can always go back to the reverted commit, checkout a branch from there and continue.
What i'd suggest in such scenario is,
git branch newBranch
: Create a new branch keeping the accedental commit, that'll preserve your development and the code so far.git reset --hard <commit hash>
(on master). That'll leave the master unmutated.Now switch to newBranch and continue with your business like nothing ever happened!
Wouldn't protecting a branch only affect the remote repo? I don't think she pushed to master.
HEAD
always points to the commit that is checked out.HEAD~
, which is the same asHEAD~1
refers toHEAD
ʼs parent.HEAD~2
is the parent ofHEAD~1
, and so on.When you
git chegkout
a different commit,HEAD
moves to that commit. When yougit commit
your changes,HEAD
moves to the newly created commit.When you do a
git log <commitish>
(where<commitish>
can be a branch name, a tag, a commit hash, or pretty much anything then unambiguously refers to a commit, and defaults toHEAD
if you donʼt specify it), Git will print that commit, its parent, the parent of that parent, and so on.Contrast that to
git reflog
which displays the commitHEAD
is pointing to, then the commitHEAD
was pointing before (and can be referred to asHEAD@{1}
), and so on.Hope that helps, happy coding!
Whoa. Thanks for this. I also didn't realize they had that difference. But it does make sense that you'd need a way to specify which parent to choose, when more than one exist.
I'd summarize as: when a commit has more than one parent,
^
lets you say which one you want,~
always returns the first.What's confusing is that each can take a number, but treats it differently.
<rev>^2
means "rev's second parent" and<rev>~2
means "rev's leftmost grandparent." It might help to think of merge commits as having left and right parents (^1
and^2
), but technically they can have more than 2.My guess is the commits became unreachable. The commits are like a tree* where some of the leaves have markers (either tags or branches) pointing to them. Any commit that's pointed to by a marker or another commit is reachable.
git log
, despite the name, is just a list of the reachable commits.Unreachable commits eventually get deleted. The
reflog
lists every commit, but being in the reflog doesn't prevent deletion.* technically a DAG, because multiple parents are possible.
reflog can even help when you accidentally drop/clear stashed changes (those that weren't even committed really yet).
? how does it work if the changes arent committed or stashed somewhere..?
Well changes should be in the stash of course. Then you accidentally lose it (via
git stash clear
orgit stash drop
). However, even if changes weren't committed, they still do have some hash tags in the repository, they are stored as so called "dangled commits". So all you have to do is find such hash and apply it viastash
command to restore. You can see an example here:stackoverflow.com/questions/89332/...
nice, thanks for the link!
Try translate this page to understand reset, checkout, branch and so on. Very good article.
miximum.fr/blog/enfin-comprendre-git/
GUI's git application provide speedup over all activity but most of users makes mistakes on GUI interface. Guy who on terminal never make kind of mistakes.
This can save many from the panic attack. Thanks for posting this.