top | item 21189256

99% of the Git commands you'll need at work, demonstrated in a single script

659 points| carodgers | 6 years ago |bitbucket.org | reply

154 comments

order
[+] trevor-e|6 years ago|reply
Maybe my workflow is a lot easier than others, but I work on a team of 10+ engineers and my Git usage is dead simple. I do everything from a GUI (Fork for macOS) and very rarely have to deal with any complicated issues that require a terminal.

- Always pull w/ rebase for the current branch.

- Always merge other branches into your current branch, eg master -> feature.

- Always stage individual chunks of code one at a time to make sure I'm committing the right stuff.

- Always squash feature branches into a single commit when merging back.

- Stash changes if needed when switching branches.

- Cherry-pick one-off commits if needed.

- Append a previous commit that I haven't pushed yet if I happened to forget something.

- For complicated merge conflicts I switch to Visual Studio Code which also has a great GUI.

I think this covers 99% of the stuff I encounter in my day-to-day.

[+] arcticbull|6 years ago|reply
I agree with basically everything you wrote except I’ve had much better experience rebasing my feature onto origin/master instead of merging master into feature. Keeps the [branch] history cleaner.
[+] Groxx|6 years ago|reply
This likely works because a) you know what you're doing (cherry-pick), and b) you're being careful (staging carefully).

Anything works when both of those prerequisites are met. You're unlikely to do the bad things that force more advanced needs.

Everyone should do this. Think back to how much time you've lost due to git problems. It'd probably take less time to learn it correctly up-front, and never have to deal with them ever again.

[+] ssully|6 years ago|reply
I am in a similar boat, except I just Githubs desktop client. In the past 4 years, I think I have had to use the command line under 10 times.
[+] danpalmer|6 years ago|reply
I agree. Almost every time I hear of someone having issues unpicking a complicated git issue it's because they were trying to be too smart with it and use every feature just because they are there.

Find a _simple_ git workflow, document it in a style guide, stick to it. Git doesn't have to be complicated.

[+] wilg|6 years ago|reply
I am similar but avoid rebasing entirely in favor of squashing. Squashing can also be used to turn a messy branch into a new branch full of nice clean independent commits.

I also don't bother appending (though my GUI lets me undo the last commit if I haven't pushed which is maybe the same thing.)

Most developers get way too fancy with Git and screw something up. I use GitHub Desktop and rarely touch the command line for Git. It has a great UI for being able to just pop over and see my current changes, and easily commit just a line or two from them to make commits other people can understand.

[+] mav3rick|6 years ago|reply
I will never understand why people use a UI for git. 99% of the time people who do that don't understand how git works. When something deviates from the normal workflow they struggle.
[+] gregmac|6 years ago|reply
Totally agree with everything on this list, with two exceptions:

* I almost always just do a regular merge to master (rather than squash).

* I use GitKraken which (in the pro version) has a great merge tool.

A lot of people seem to want "clean history" so just I'd just like to put it out there that it's not really necessary (there's nothing wrong with it, of course), and regular merges work just fine. In my experience, the two main reasons I look at git history are:

(1) Checking when a feature was done and what releases it got into

(2) Finding out why a particular line of code exists (blame)

For (1), with software with numbered releases, you end up following the branches anyway. Having the individual commits from feature branches makes you scroll more, but it doesn't make it any harder to follow. If you really don't like seeing them, you can hide anything but merge commits.

Even simpler, if all you care about is whether a given feature branch is done (merged) or not, that's easy to see and the same as a squash-merge workflow.

With continuously-deployed ("cloud") services, things are even simpler - you start at the hash currently deployed and go backwards. It makes no difference if there's one branch or many feature branches (other than scrolling past more granularity).

For (2), the greater granularity from individual commits is generally useful (at least provided that each commit has a ticket number and useful description), and squashing erases this detail.

Also, a nice thing is if you end up merging the same branch to multiple places (master and a release branch, for example) it's obvious what happened by looking at the tree. Contrast to if you cherry pick a squash merge commit, the only way to see that is to read both commits and realize they're the same -- and this is much less obvious if there's other commits between them.

Basically, squash merging doesn't help with either of these, and in fact actively hinders (2).

My team has been doing this for a few years, and I'm not even sure if it was a conscious decision to merge this way (or not do squash merge) but we've had no reason to change. It does depend on every commit being well-formed, but this is pretty easy to ensure in a paid team that works on this every day (whereas with open source I'm not sure it'd work well).

Anyway, like many things in git, there's more than one way to do it, and there's no clear "right" or "wrong" way.

[+] marcosdumay|6 years ago|reply
Nearly every time that I google a git command, it's something related to tags.
[+] qmmmur|6 years ago|reply
Why do you always rebase? Is your master essentially the stable branch of the program you are collaborating on?
[+] pjmlp|6 years ago|reply
Same here but from Visual Studio, Eclipse and Tortoise GIT, while missing Subversion and Mercurial.
[+] 5trokerac3|6 years ago|reply
In my experience, if you ever use more than clone, fetch, pull, push, checkout, merge(tool), reset, add, and commit then somebody messed up.
[+] Munksgaard|6 years ago|reply
I know this has been mentioned a million times on here, but for the off chance that someone hasn't heard about it before I'm going to completely disregard that and say that Magit for Emacs is an incredibly helpful tool for interfacing with git repositories that I couldn't imagine working without it. It's by far the best interface to a version control system that I've ever used. It has helped me understand how git works behind the scenes, and allows me to effortlessly work with branching, stashes, merging, rebasing, remotes and much more, without remembering a bunch of arcane git commands.
[+] panpanna|6 years ago|reply
I feel the list of useful for commands should be much shorter:

    git add/rm/commit/status/push
    git branch/checkout/merge/rebase
    git tag/push --tag
Anything else should be handled by policies. If you get bad PR, reject it instead of trying to fix it using some complex sequence of git commands.
[+] simiones|6 years ago|reply
You need to add `git stash` to move to a different branch while having changes wide open.

You also need `git log` with all sorts of arcane options if you actually want to use the history.

[+] carodgers|6 years ago|reply
I got a little tired of running to Google every time I needed a non-trivial git command, so I set out to identify all (and only) the git commands I require for my day-to-day and capture them in one place. The result is this script. It can be run fully on your local machine, no remote accounts required. (But it still shows how to use remote repos!)

I'd also be interested to hear what git commands others use frequently (that don't involve a GUI). I'm curious to know which workloads might require some of git's more advanced features on a regular basis.

[+] katet|6 years ago|reply
A couple of random addendums (although these aren't necessarily what you'd use day to day)

git diff --color-moved

(seriously, read through the man page for git diff sometime)

git log -p --all -- <path/to/file>

(I use this with multiple remotes, so I can track changes in my fork and in upstream when looking for context around a file)

git cherry-pick -x

(for automatically adding a reference to the original commit)

A couple more, but I think they're really quite specific to my personal workflow and responsibilities

[+] coldpie|6 years ago|reply
> I got a little tired of running to Google every time I needed a non-trivial git command

Have you read through the gittutorial, gittutorial-2, and especially the gitcore-tutorial manpages[1]? Reading those guides and actually following the steps and examining the results on disk was extremely helpful for me in understanding how Git actually works. Once you've got that understanding, the Git UI seems less arbitrary. You can start to see how it was put together over the years, which should help you use the tool more intuitively and effectively.

> I'm curious to know which workloads might require some of git's more advanced features on a regular basis.

I work on a very large and very old (mid-90s) project, so history-diving and diffing branches is very useful for me. I use all of git-blame, git-show, and git-diff to examine history to learn how the code came to be as it is. Even git-cat-file comes up occasionally when I just want to look at some old object I happen to have a hash for and don't want to look up properly through the porcelain.

We also maintain a bunch of branches and backport modern commits onto legacy branches. git-rebase can help for this, but more often I find myself doing it manually (well, with a bash script) with git-cherry-pick, as it's easier to work with commits without being in the middle of a rebase operation. Knowing git-log's many options to massage history into a useful form for my work comes in very handy here, too.

More details on the rebasing procedure I use: https://github.com/ValveSoftware/Proton/blob/proton_4.11/doc...

Here's some of the tooling I use often. For Git stuff, see pick_commits and gitconfig https://gitlab.com/mywinetools/mywinetools/

[1] I know, I know, no one likes studying and learning how to use a tool. But sometimes you gotta if you want to use the tool effectively.

[+] RealityVoid|6 years ago|reply
I just found out today about git worktree[1], and I think it's a very powerful feature more people should know about, but it seems used less than it could.

Basically, you can do a working copy of the git environment without pulling the repo again, so you have only one .git folder.

A godsend if you, like me, work on gigantic repos that build unbearably slowly and want to be able to use multiple instances of the same repo at the same time.

[1] https://git-scm.com/docs/git-worktree

[+] jomar|6 years ago|reply
Compared to the previous technique of creating a new separate local clone for unrelated simultaneous work on a project, it's also glorious when it comes time to clean up and delete no-longer-needed extra working directories.

After `make clean` and `git status --ignored` shows nothing worth preserving, you can delete the worktree (via `git worktree remove`) with impunity. No more paranoid checking that there is no valuable work stashed or hiding in other branches before typing `rm -rf`, as those are shared with the main worktree so won't be lost.

[+] aequitas|6 years ago|reply
Try Gitless[0]. It's an alternative 'UI' to Git which is kind of build top down instead of bottom up. The commands are much higher in the abstraction tree and clear single operations and dropping some concepts like the staging area. It operates on the Git database the same way 'normal' Git does so you can always fall back.

[0] https://gitless.com/

[+] sidpatil|6 years ago|reply
> It's an alternative 'UI' to Git

Also known as a porcelain, as opposed to the low-level commands known as the plumbing.

[+] vfc1|6 years ago|reply
Thanks for sharing, but I feel like it's more like 99.999%. The essential commands for development are really a lot less than this. Maybe it's a list for release managers / sys admins?

Committing, pushing, handling local branches, updating, merging, rebasing, cherry-picking, squashing and stashing is almost all that everyone uses, and several of those not even on a daily basis.

[+] niark|6 years ago|reply
After years of wanderings, I've settled with Fork which is a a delightful GUI. Polished, feature-rich, and still improving on a regular basis. Kudos to the authors!

[0] https://git-fork.com/

[+] sixstringtheory|6 years ago|reply
Same, I spend about 50% of my time in git on the command line, the other 50% in Fork. I've used SourceTree -> Tower -> Fork and I'm very happy with where I'm at now.
[+] therealdrag0|6 years ago|reply
I switched from SourceTree a few months ago after seeing Fork on HN. I couldn't be happier with it!

Love seeing high-quality software developed by just 2 people.

[+] liquidify|6 years ago|reply
hmm why no linux?
[+] HocusLocus|6 years ago|reply
Ran this script, it uploaded my whole network to Github as an open source project and sent a broadcast notification to Krebs On Security.
[+] hnhg|6 years ago|reply
Is that what you wanted?
[+] pastrami_panda|6 years ago|reply
'git add -i' is my new favorite. When you want to stage certain files but don't want to type out the paths over and over again to deeply nested files
[+] wyclif|6 years ago|reply
One tip I give people who feel overwhelmed by Git is that unless you are an edge case, you can probably do most of what you need to get done with these six commands:

branch checkout add commit pull push

Reading and understanding the documentation for those six core commands isn't a big investment, and it will pay off if you're doing software or documentation development.

[+] JamesQuigley|6 years ago|reply
I'm personally a huge fan of https://www.gitkraken.com/ (I also used to work there.) Don't have to memorize git cli commands and get beautiful visuals on top of that.
[+] mroche|6 years ago|reply
It’s been a long span of time since I’ve used GitKraken or Atlassian Sourcetree, but GK had some serious performance issues with larger repos in my experience. Very clean app, though, and I did enjoy it.

Right now, Im partial to Sublime Merge[0] as it’s fast, has a clean UI for diffing, shares many similarities with Sublime, and also shows the use what git commands they’re running by hovering. It can be a very effective tool for learning git. It has the same evaluation structure as Sublime, so that’s a bonus as well.

[0] https://www.sublimemerge.com/

[+] jackcodes|6 years ago|reply
I do appreciate that this is probably a cracking tool for beginners and juniors. If it was skilling someone up to git using this tool or not at all, damn right I’m choosing this.

But I can’t bring myself to run a web browser to run git commands either. The git binary on my system comes out at 2.5Mb and the MacOS .app bundle for this is 346.5Mb.

[+] BalinKing|6 years ago|reply
Hi, James (it's Josh Grosso)! Are you not at Axosoft anymore? If not, where'd you move to (and how are you doing either way)?
[+] rinchik|6 years ago|reply
ugh i hate GUIs, for me those are a middle man. With cli, i can "feel" git. with GUI i'm just telling a 3rd party to talk with git for me. That 3rd party can also screw up some communication, just like in telephone game.
[+] thrower123|6 years ago|reply
This kind of thing is why I'm very glad that the Team Explorer git plugin in Visual Studio has become decent enough that I don't have to drop into the cmd line, pretty much ever.
[+] ShteiLoups|6 years ago|reply
I used to live and die by the command line.

Then I met sublime-merge. And fell in love. It is the only Gui I find more efficient and beautiful than my terminal. I highly reccomend it.

[+] KuhlMensch|6 years ago|reply
I'd say I literally use pickaxe (-S) and the -G one a few times a week. Often to answer questions I hear around the office. If you are not familiar with it, I think its an amazing. Err... I guess...check it:

http://www.philandstuff.com/2014/02/09/git-pickaxe.html

Also I do allot of

git reset --soft HEAD;

(pick-hunks-with-GUI);

git stash -u -k;

run-test.sh;

git commit -m "blah"`

[+] anreekoh|6 years ago|reply
If you want git on the command-line, but don’t want to remember commands, try lazygit[0], it’s changed what I’m comfortable doing with git because it can tell me at any given moment what I can do.

[0]: https://github.com/jesseduffield/lazygit

[+] jeena|6 years ago|reply
The example commit messages are triggering me.
[+] jnurmine|6 years ago|reply
Silly little alias, "git top".

  [alias]
          # top 10
          top = !sh -c 'git log --oneline|head -10'

It shows the top 10 commits. I use it several times every day, to orient myself while flipping between multiple repositories and branches.