Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
GitTips (kernel.org)
166 points by gkst on Aug 15, 2016 | hide | past | favorite | 55 comments


My number one git tip for day to day use rather than specific scenarios is setting up aliases for everything.

Along with the ones provided by the git oh-my-zh plugin I have these[0].

Some examples

+ gco - git checkout

+ ga - git add

+ gc - git commit

+ gp - git push

+ gl - git pull

+ gpc - Pushes current branch to origin

+ gpcfl - Force pushes the current branch to origin using --force-with-lease

+ glc - Pulls curent branch from origin

This is my favourite though

function goops { git add -A "$@" && git commit --amend --no-edit && gpcfl }

Used like this `goops file`, it adds the file, amends the last commits and force pushes the branch. Super useful because I tend to realise I forgot something just after I push. Don't do this on shared branches though, force pushing should only happen to branches were you are the only one working on the branch or in coordination with anyone else working on the branch.

0: https://github.com/k0nserv/dotfiles/blob/master/files/zshrc....


> ... `goops file`, it adds the file, amends the last commits and force pushes the branch

Note that you should only ever do this if you are absolutely sure that you are the only person pushing to that branch.

You should consider using "--force-with-lease" instead of "--force". Otherwise you'll sooner or later overwrite a coworker's push without a trace. Maybe they'll notice know Git good enough to fix this, but it would still be very, very annoying.

EDIT: Changed "repository" to "branch", mention "--force-with-lease".


> Note that you should only ever do this if you are absolutely sure that you are the only person pushing to that repository.

I would revise this to say the only person pushing to that branch. But yeah.


push --force-with-lease can mitigate accidental overwrites though


Thanks for the hint. I wasn't aware of that option.


Note that you should only ever do this if you are absolutely sure that you are the only person pushing to that branch.

I've worked with multiple orgs where the convention for shared repos was to use branch names of the form <user>/<topic>, e.g. bowie/pipeline-v2. Such "user" branches should generally never be pushed to by anyone other than the dev they were named for. This has worked great to allow individuals to have visibility and/or backups of work-in-progress while avoiding lossage due to any branch cleanup prior to PR, etc.


Definitely, don't force push unless you know what you are doing and the implications of force pushing. On the other hand don't blindly listen to people who tell you that force pushing is bad and should always be avoided


You can use --force-with-lease


you'll sooner or later overwrite a coworker's push without a trace

This is the kind of thing that makes it hard to see why git has become the One True DVCS - you can not just overwrite history but actually lose other people's work quite easily (presumably the commit also vanishes from their repo when they next pull?)


I think that's an unfair characterisation of git. Pretty much everything you can read online recommends against force pushing and it's definitely not part of any workflow recommended to beginners. Even with a force pushed branch when the person whose work has been overwritten tries to pull the pull will get reject and they'll retain the local copies of their commits. It's possible to resolve this problem as long as the person with overwritten commit doesn't delete their local copies.

Force pushing is super powerful when you learn to use git properly, but it's also like a gun with no safety so it's easy to shoot yourself in the foot if you don't know what you are doing.


No, the commit doesn't just vanish when they pull. They'll be asked to reconcile their local repo with the diverged upstream.


I agree, Mercurial is a lot better in this regard.


Alternatively, if you like to stay close to the git commands themselves (which is very helpful when helping colleagues), use a git shell such as git sh¹.

After starting the git shell in the terminal (just git sh for the eponymous program) all command are simply the same as in git, only without git in front of them (so add, push, etc.). Aliases work as expected of course, so st for status, and d for diff are possible too.

These type of shells have the added benefit of a status prompt showing the basic git info, such as current branch and number of commits ahead or behind the tracked branch.

1: https://github.com/rtomayko/git-sh


I use scm_breeze[0] which adds these shortcuts + has numbered file shortcuts, which allow you to type 'ga 1 3' to add files 1 and 3 (numbers are shown by 'gs' - git status).

[0] https://github.com/ndbroadbent/scm_breeze


What does the `git add -A "$@"` do? I tried it just now, and it was equivalent to doing `git add .` (although I am using bash instead of ZSH). I have this alias for myself: `git commit -a --amend --no-edit && git push --force-with-lease`, which isn't perfect but close enough.


You can pass arguments so `goops app tests` only adds files in app and tests


Cool thanks! I just got that working for myself, with the extra logic of doing `git add -u` if there were no arguments.


I don't use aliases for the main git functions because they are easy enough to type anyway, a good idea to remember, and many of these operations are not things you want to do accidentally because of a split-second typo. The only exception is 'gs' for 'git status' because I use that more-or-less reflexively and it's completely safe.

What I do have is loads of aliases for getting different logs and graphs, because all the sensible formatting options are impossible to remember. I would be lost without these. Straight from my bash profile:

  # Quick summary git log variants (with and without hash, with condensed whitespace or tabs)
  alias 'gl=git --no-pager log --pretty=tformat:"%ad %an: %s" --date=short -n 15'
  alias 'gll=git --no-pager log --pretty=tformat:"%ad %h %an: %s" --date=short -n 15'
  alias 'glxl=git --no-pager log --pretty=tformat:"%ad %H %an: %s" -n 15'
  alias 'glt=git --no-pager log --pretty=tformat:"%ad%x09%an%x09%s" --date=short -n 15'
  alias 'gllt=git --no-pager log --pretty=tformat:"%ad%x09%H%x09%an%x09%s" --date=short -n 15'

  # Same, in reverse order, plus show slightly more entries (most recent won't scroll off top of screen)
  alias 'glr=git --no-pager log --reverse --pretty=tformat:"%ad %an: %s" --date=short -n 25'
  alias 'gllr=git --no-pager log --reverse --pretty=tformat:"%ad %h %an: %s" --date=short -n 25'
  alias 'gltr=git --no-pager log --reverse --pretty=tformat:"%ad%x09%an%x09%s" --date=short -n 25'
  alias 'glltr=git --no-pager log --reverse --pretty=tformat:"%ad%x09%H%x09%an%x09%s" --date=short -n 25'

  # Quick Git Graph viewing
  # Usage: gg <list of branches> | gg --all
  alias 'gg=git --no-pager log --decorate --oneline --graph -n 25'
  alias 'gga=gg --all'
There's a naming convention of 'gl' for 'git log' and 'gg' for 'git graph' where 'll' means "log, long" and "lxl" means "log, extra long". Adding 't' means tab-separated for piping & parsing, or copying into a spreadsheet and 'r' means reverse (which I would actually consider 'forwards' but I try to stick with git conventions even though it's the opposite of say, svn). I did not create every permutation, but all of these variants are useful quite often and if I try to run a variant that doesn't exist, I just add it quickly so it's there next time.


https://GitHub.com/GitAlias provides many git aliases like yours, plus ones for topic branches, packing, publishing, logging, and more.

I'm the maintainer so feel free to suggest ones.


You might be interested in this: https://gitlab.com/mikegerwitz/git-shortmaps


I'd rather use something like this: http://gggritso.com/human-git-aliases


Other useful ones I use everyday:

gdh -- git diff HEAD (what have I modified since last commit)

gl -- git log --graph --oneline --all --decorate (ASCII graph of all commits on all branches)


Or use magit! (And spacemacs)


My most important git tip is: use Magit (https://github.com/magit/magit). It really is a huge step forward from using the git CLI — but, unlike many UIs to CLI tools, it actually helps one learn the CLI, but presenting flags and git subcommands. Thus, it both supersedes the git CLI and teaches it, just in case one is ever on a computer without Magit.


Interesting, I tend to recommend people who want to use a UI tool to first learn how to use git from the CLI because many times UI tools are leaky abstraction and sometimes they are flat out wrong and rename concepts. This sounds like it'd be perfect if it wasn't for the emacs aspect of it.


> This sounds like it'd be perfect if it wasn't for the emacs aspect of it.

If you prefer vi you can always use spacemacs …

If you prefer Atom or SublimeText, well then: come over to the light side of the Force grin


Spacemacs is slow, clunky and always messed up (I tried it 6 months ago and it conflicted with Ergoemacs pretty badly).

Also, _both_ vim and Emacs are horrible UI. Vi was designed for slow terminals and a particular keyboard with no arrows; ghjk for navigation is terrible, always pressing the wrong key. Emacs was designed (C-w) evolved from macros for Space Cadet keyboard with lots of modifier keys. How these two archeological curiosities are still praised for being good modern text editors, escapes my mind.

(I use both vim and Emacs as I enjoy working in terminal, and I hate them both. Sadly, there is no good text editor like Sublime or Atom for console).


I have been using spacemacs and I can't really go back. Some parts are clunky, but it feels like I am riding a battle cruiser. I can literally do anything.

I have gone on the editor search for a while, and now I have settled. Can't be more happy!

The editors I might switch to are Acme, LightTable, or Lamdu, but probably unlikely.


It's more that the people who usually want to use a UI tool are already very UI oriented, so they'll not use emacs or vim. Probably PyCharm, Visual Studio or some other heavy IDE.


The awesome `tig` gives you a lot of that in a standalone tool.

I'm not sure how much overlap there is in functionality, I have not even used all the features.

Here's a good blog article on it: http://blogs.atlassian.com/2013/05/git-tig/


A million times this. I started using Emacs (actually Spacemacs) just to be able to learn how to use magit after reading so many people praising it. After around 6 months, I don't even touch the terminal for git, except to do 'git init', which I'm sure there is a way to do from within magit. I donated a bit, and lately I'm thinking of donating something more substantial, >50. Do yourself a favor and try magit for a month with Emacs or Spacemacs, whatever you're most comfortable with. And then maybe do the amazing programmer behind magit a favor, and donate to help him.


> After around 6 months, I don't even touch the terminal for git, except to do 'git init', which I'm sure there is a way to do from within magit.

M-x magit-init :-)


Another reason to try emacs for magit/git is the integration with emacs' version control functions. It's very easy to C-x v l to see the log of a file under git, and then use 'd' to see the diff and 'f' to actually look at the full file. This can be helpful when people are still trying to figure out how to use hashes over revision numbers.


If you're looking for something with UI, smartgit in cross platform and make git for me usable.


I wonder why this page doesn't have one of the most frequently asked and rated question: "How to undo last commits in Git". It's rated 11k times so far.

[1] http://stackoverflow.com/questions/927358/how-to-undo-last-c...


[flagged]


Do you think if I had a choice, I would have chosen Git? Ugh.

No, I'm forced to use it as a condition of employment.

You're right: I'm not qualified to use it, I disqualify myself with the rule "only use software that at least pretends to be usable", but that doesn't mean I have a choice in the matter.


> Do you think if I had a choice, I would have chosen Git? Ugh.

> No, I'm forced to use it as a condition of employment.

And you deem it a valid reason to avoid learning the tool you use? O_o


I don't want to be able to think the same way people who think Git is a great tool think. If that makes sense.

If I get brainwashed into thinking Git is well-designed or good in any way, I'm afraid I'll completely lose my ability to design quality user interfaces.


Git with its interface may be rough, but this is merely a superficial trait. The same category as saying that Erlang is fugly because its syntax derives from Prolog. Who cares? It's mechanics and semantics, respectively, that matter.

I can whack git repository with a hammer and achieve good, reliable results this way (and I already needed it several times in weird scenarios; I wouldn't get far with Hg under the same circumstances). Pretty much the same case as with Linux OS: all the internals are easily accessible, and user interface is just good enough for me to use.


> Who cares?

I care.

I want to build software normal human beings can actually use. Git is not that. Learning more about Git is me going in the wrong direction entirely. I don't want to go in the wrong direction, I want to go in the right direction.


Few people are really qualified to use it. Most are required to use it and not given the required weeks of training.


That's a shame it takes them weeks to read three quite comprehensible man pages to think up two different ways of changing commit history.

How did we actually get to the point where it takes weeks of training to use git, when I remember learning how to use it in a day or two, ten years ago (when it was much less usable and documented), and for a (far from trivial) use case of being a helper tool for off-line work with Subversion?


And even if it does take someone a month to learn Git, is that not worth it? You'll be using it pretty much every day for a decade, if not longer.


the desire would be to have a system which let you get started relatively quickly, and learn it more in depth as you have need to.

git really doesn't work this way because unless you manage your branching and merging in a sympathetic way (to both git and your peers), you can get very thoroughly punished.


Probably because you have 10 years of experience?

Git is a mess, but popular tool and many peopled are forced to use it instead of some sane system.


> Probably because you have 10 years of experience?

I was learning git a decade ago, and all it took was at most two days of reading. And yes, this includes the idea on how to rewrite commit history (actually another one, very low-level; I don't expect anybody to ever think of this way for the task).

I didn't have StackOverflow or plethora of tutorials on web that are present today.

> Git is a mess

I keep hearing that, but once upon a time (seven? years ago) I tried learning Mercurial, this paragon of usability, and I couldn't figure out one of the simpler things: how to setup a repository to merge changes from two other repositories without specifying full paths.

Given that, either I'm very smart, because I picked up git so quickly, but so-praised Mercurial "is a mess", or I'm very stupid, because I couldn't figure so simple Mercurial function, but then what does it say about people who can't read the fsckin' git docs?


A nice tip from Scott Chacon by way of Conrad Parker[0] is to create `git lol` and `git lola` aliases to display a color-coded view of history layout in the console. Summary: add the following to your `~/.gitconfig`.

    [alias]
        lol = log --graph --decorate --pretty=oneline --abbrev-commit
        lola = log --graph --decorate --pretty=oneline --abbrev-commit --all
    [color]
        branch = auto
        diff = auto
        interactive = auto
        status = auto
[0]: http://blog.kfish.org/2010/04/git-lola.html


You can use the mnemonic "dog" or "adog". Note: the `--abbrev-commit` is redundant due to the `--pretty=oneline`.


> Note: the `--abbrev-commit` is redundant due to the `--pretty=oneline`

I've tried it and this is not true on my git version (1.9.1) - without the "--abbrev-commit", git displays the full hash


My favorite Git tip is to use SmartGit.

http://www.syntevo.com/smartgit/

It gives you so much more visibility into the state of your repo, and many operations that take several Git commands are just a single step in SmartGit. And it does show you the underlying commands it uses.

I like the way SmartGit unifies things like the reflog. If you "lose" some commits because of an amended commit or a rebase gone bad, you don't have to hunt through the reflog looking at hashes and commit messages, just click the Recyclable Commits checkbox and everything in the reflog shows up as normal commits in your log. You can immediately look through these commits and see the changes without having to check them out.

I've also heard good things about SourceTree, but I can definitely vouch for SmartGit.


My personal favorite (though I thankfully haven't had a chance to use it yet):

    alias gitfire='git checkout -b fire-`date +"%Y%m%d-%H%M%S"` && git add -A && git commit -am "The roof is on fire" && git push origin HEAD'


Hacks upon hacks upon hacks.

On the inside, Git is a thing of beauty, marvel of engineering. On the outside, it is a mess of inconsistent command line options, terrible documentation, and snobbish community that thinks everything of this is fine and small surface details are irrelevant as long as the core works exactly as advertised. They probably also work in Emacs with default keymap.


That's what I felt too. I started using mercurial and I never looked back at git. Mercurial CLI is a pleasure to work with.


Without starting a VCS war:

+1 for Mercurial.

If, like me, you do not have a good memory for arbitrary syntax, then mercurial is a lot easier. Takes a bit of cognitive load away from using your VCS. It is thus also much easier to learn than git, so the cost of giving it a whirl is much lower.

It also has that nice feeling of being designed with the end user interface in mind, which is satisfying if you care about such things. I enjoy using tools that give me clarity about what I'm doing, and mercurial achieves this by carefully separating the different actions VCS must support.

(I regularly use both systems and have done so for years. I am not a power user. I use mercurial whenever I have a choice).


> On the inside, Git is a thing of beauty, marvel of engineering. On the outside, it is a mess of inconsistent command line options, terrible documentation, and snobbish community that thinks everything of this is fine and small surface details are irrelevant as long as the core works exactly as advertised

The core working exactly as advertised is vitally important! Rotten core + shiny, 'user-friendly' exterior would be a polished turd.

I do agree - the outside of git didn't have to be ugly and I'm yet to meet any git 'apologist' who disagrees or thinks it's fine. In mitigation though, the git command can be wrapped by friendlier CLI tools or GUIs. Git has succeeded largely in part of the massive tooling around it - things like GitHub would have been less likely to exist had Git's internal data structures been opaque or poorly designed.

It might be instructive to hear it from the horses mouth: Linux, on git "git actually has a simple design, with stable and reasonably well-documented data structures. In fact, I'm a huge proponent of designing your code around the data, rather than the other way around, and I think it's one of the reasons git has been fairly successful […] I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important."




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

Search: