Hacker News new | past | comments | ask | show | jobs | submit login
Git commands to know just after you get the basics (codersbible.com)
104 points by mdziubek on April 4, 2020 | hide | past | favorite | 36 comments



Some other Git features that I find super useful, which past colleagues of mine haven't known about (which maybe suggests they are not universally known).

git rev-parse branch-name: gets the hash of a branch name, useful for verifying two branches are at the same place (so "git rev-parse HEAD" gets the current hash)

The ^ and ~ notations for navigating commits: my_branch^ points to the commit 1 before my_branch, and can be repeated multiple times, ie. my_branch^^^ to get the commit 3 from the top. Likewise the tilda notation allows one to jump a fixed number of commits up: my_branch~10 is the commit 10 above my_branch.

git rebase -i HEAD~10: interactively rebase the last 10 commits. Easy way to re-order, squash, drop, and/or edit the commit messages of recent history in a single git command.


This one is interesting, because if I recall correctly, if you are using the single symbol they more or less mean the same thing. You can do ~~~ or ^^^ and get to the same spot

The difference is in their numerical notion. ~N means go to my Nth first parent. Where ^N means my Nth parent, which is really only valuable/useful on merge commits (Or more specifically octopus merges that merge more than two commits)

This is why ~ and ^ in the single form mean the same thing.

So, in one mental model of the DAG you can think of ^ as horizontal navigation (Right) and ~ as vertical (Down)


Oh cool! That's good to know. Sadly too late to edit my original message, but have upvoted yours so people won't learn from my errors :)


> git rev-parse branch-name: gets the hash of a branch name, useful for verifying two branches are at the same place

I believe the same thing can be done by running git log --oneline -n1 branch-name (though you will also get the commit message title in addition to the sha).

> my_branch^ points to the commit 1 before my_branch, and can be repeated multiple times, ie. my_branch^^^ to get the commit 3 from the top.

The ^ notation only references the first parent of the commit. You would have to do something like commitish^2 to reference the second parent (though this would only be an issue for merge commits or any commit that has more than one parent).


My god, we have to use git in school and no one knows about rebasing. A group member made commits with profanity in messages (ha-ha, so funny, now how about some useful messages though?) and it turned out at the end we had to submit the repo. Everyone was panicking until I told them I could change the message in literally half a minute.

Rebasing cleans up my commits so much. It is nice being able to have a chain of nice, logical commits even in the middle of a hairy refactor.


A couple of other ways to see if two branches are the same or not

  git diff branch1 branch2
git show displays any additional branches that are the same.

  $ git show -q
  commit 2ee0fd3e2717a352b6ded617184be280cb55e78c (HEAD -> master, foo)
  ...


Just learned git rebase -i last week. Added tip: git rebase --abort at any point in the process if you're not sure if you did the right thing.


By far my most used git command is this alias for a much more condensed, prettified log:

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

From https://coderwall.com/p/euwpig/a-better-git-log


It doesn't show which commits have two parents. Which is usually useful for a `git revert`.


My favourite is real simple - it just shows me which branches/tags are most current, with the last worked-on at the top ..

    'git for-each-ref --sort=-committerdate'
Helps me keep my head around what branches are what ..


In rebase-happy workflows the commit date doesn't mean much.


For me, I found it very useful to stop using tracking branches. This means I move all of my branch pointers manually and once you get used to it, you’ll begin to find rebases and cherry-picks more intuitive. In fact, it’s made me really distaste merge commits in general.

Flow might be something like:

    git checkout master
    git checkout -b my_branch
    git push origin my_branch
    ...
    git fetch
    git log -p origin/my_branch
    git reset --hard origin/my_branch


While a lot of git commands can compete for the title of the most useful, I believe the combination of git reflog and git reset is what can transform the git user from someone who lives in fear of their tool to someone who loves it.

Know reflog and you stop being afraid of losing your work if you mess up, know reflog and reset and you stop being afraid of not being able to fix things if you mess up.


Or, if you use SourceTree, you don't need to struggle at all.


git reset --hard can be pretty destructive when applied at the wrong moment. When reverting changes in selected files, my preferred way is to use git checkout selectively.


Agreed, and there's also git restore now, which might be a bit more intuitive.


next commands I find very useful

  git diff # see diff 
  git diff master..develop # see diff between branches
  git show <commit> # see changes in specific commit
  git log -p <file> # see log for specific file with diff
  git checkout - # checkout in previous branch


git bisect is the command everyone should learn. With a single command (such as a test you just wrote) you can have git do a binary search across any number of commits and find exactly when the bug occurred.


git bisect and got blame are underrated tools, that in my opinion get lost in the conversation about should-you-squash-or-not. They really have diminishing returns when you start squashing huge feature branches into a single commit.


A git alias I use is "git preb", which stands for "pull with rebase". It rebases my commits on top of origin using a merge algorithm, which is smarter than the default which uses patches and often causes merge conflicts. Its definition is - iirc, typing this on my mobile - "pull --rebase -s recursive". Now I don't push any useless merge commits like "Merge origin/develop into develop".


I wish I had learnt about gitignore sooner when I first learnt to use git. Especially if you are using an IDE and it generates a ton of files.


For IDE files a global ignore file is useful, then one doesn't have to repeat this for all repos and not all contributors need to add their IDE's files to a shared file. For local there is also .git/info/exclude per repo.


Yes, that’s good advice. I was referring to the concept of gitignore in general. At least when I learnt git from some tutorials, gitignore was treated like an advanced topic and I was fumbling with git for a while with all these artefacts creeping into my repo until I learnt of this simple solution


My most used git command is `git help`. My soon-to-be favorite I just discovered is `git config --global alias`.


Learning git is race-to-reflog, so you can undo your learning mistakes.


My most useful tool for working with and fixing weird branch structures is the graph based log output together with `git branch -f move_me to_here`


I really don't think git reset --hard should be at the top of a list of git commands intended for beginners.


Yes, knowing “just enough to be dangerous” is a thing and this article just doused it with gasoline.


and yet is one of the most useful commands for fixing mistakes made by beginners . . .


Though it would probably be better to tell beginners to run git stash save first. Then they wouldn't lose changes they made to the files before running a hard reset.


Ideally disable force pushes on master branches of a repo to prevent people who screw up to also also break upstream. You can still lose some work, but at least not the complete repo.


Beginners use this command all of the time when they back themselves against a wall and can’t get out. It’s nice to have an escape ladder when you’re beginning.


The alternative for a beginner is rm -rf repo && git clone repo

How is that better?


"Someone told me git reset --hard. Oh shit!!! My extant work is all gone!"

"Hmm, how to start from scratch? I guess I could save a few files, delete the workspace with good old trusty rm -rf, clone again, and restore those few files."

If you can't see the difference between those two...

Yes, the Git power user will know how to "start from scratch" without really starting from scratch and without losing extant work they'd rather save. And beginner users can do the second of the above. But teach a beginner to use git reset --hard and they'll hate Git and they'll hate you.


OK, good point.


Obligatory xkcd: https://xkcd.com/1597/




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: