
Git Tips - akras14
http://www.alexkras.com/19-git-tips-for-everyday-use/
======
majewsky
Here's my favorite git oneliner:

    
    
      git push origin --delete $(git branch --merged origin/master -r | grep -v master | grep origin | cut -d/ -f2-)
    

It deletes all remote branches that are merged into the remote master. Because
people always forget to click the "Delete branch" button after merging their
pull requests.

EDIT: And another thing. Turn all your Git aliases into shell aliases (e.g.
"git status" is aliased to "git st" is aliased to just "st" on my system) with
this one weird trick!
[https://github.com/majewsky/devenv/blob/2c4252d37597617a493f...](https://github.com/majewsky/devenv/blob/2c4252d37597617a493f1addadacfbf8d88b4942/toplevel/zshrc#L55-L59)

~~~
Tharkun
Why would you want to delete merged branches? i like to keep them. It's not
costing you any storage.

~~~
Spiritus
Personally because it makes both `git branch -a` and tab-completing a branch
virtually useless because there's just too many branches.

~~~
majewsky
Exactly.

------
epmatsw
Love #16 and the associated article. I cringe when I see something like "js
fix" as a commit message.

However, not on board with the hate for rebase. If it's your feature branch
and you aren't sharing it with others, I'd much rather get a cleaned up PR
than one filled with junk commits because the author was afraid to rebase.

~~~
marktd
Nitpick with #16: I don't like when there is no "why" associated with a style
rule. I'm speaking specifically to #3, "Capitalize the subject line". Why is
this preferred to not capitalizing a subject line? Is there a reason, or is it
an arbitrary decision (which would be fine - sometimes a style decision is,
"We need a standard, and we chose this one." But I think the author of the
style guide should explain that that's what they're doing).

But in general I liked the article. It's under-appreciated how helpful a good
commit log is.

~~~
jcrites
Capitalize the commit message because ...

Sometimes commit message deserves to be moderately long, like a paragraph or
more. If one did not reference a code review or issue tracker link, for
example, the need would likely be common. Even with an issue tracker there's
value in capturing a few sentences of detail and sometimes more in the commit.

By capitalizing the commit message, it is natural to extend it from a single
sentence phrase to a paragraph with an introductory sentence. I think of
commit messages as analogous to JavaDoc where the first sentence or first line
is taken as the subject, or like a document with a heading. It would be silly
for short commit messages not to use capitalization while long do. A
capitalized message works as a short description of the intro to a paragraph.
Generally. once you're writing more than a single standalone sentence,
capitalize. In a permanent medium where it can be either one, also capitalize.

A capitalized sentence or sentence fragment works in many contexts, like
within a document or email. It would be annoying to convert going back and
forth. Lastly, commit messages can sometimes act as names or proper nouns, and
capitalization reinforces that role. Capitalization looks better as project or
item headers in an issue tracker, and so to the extent that commits follow
items, it's nice to consistently capitalize.

Capitalize commit messages because when Git tools generate commit messages,
they generate capitalized ones. (Be consistent.)

I grok not capitalizing IM or IRC or other chat conversations, though I do if
I start writing messages longer than a sentence. For everything but IM,
capitalization constitutes the norm and good professional style.

This rationale might not be entirely satisfying, because why does English have
capitalization to begin with? That's a linguistic question I don't know the
answer to. However, I do know that the norms that lead to sentence
capitalization also apply to commit messages and code documentation Not
capitalizing them feels like refusing to capitalize any other writing: a
potential distraction from the content.

~~~
mbrock
Most of my commits start with a component name prefix and a colon. I don't
capitalize those. I still write literate English commit message bodies.

~~~
jcrites
That sounds reasonable to me.

    
    
      foo: Add utf8 support
    

If the component name is conventionally written in lower case, because it's a
technical term, then I think a comment written in this way counts as good
style. I might choose to capitalize Foo myself, but I think foo is defensible
in that context.

------
yes_or_gnome
I'm an avid supporter of rebasing over merging. I'll refrain from getting into
my workflow, but here's what i want to say: For the love of all that is holy,
never squash a merge commit nor squash onto a merge commit.

Squashing a merge commit is a perfect way to reintroduce old code back into
master.

Squashing onto a merge commit is great way to lose changes. It's been a while
since I have tried this, but creating a didactic repo if fairly easy. Create a
repo with two feature branches, a file on each of master and the feature
branches, merge featureA to featureB, make some changes or delete a file,
`commit --amend` on the merge, and merge featureB to master. Then use `git
cat-file` to look at those commits and commit trees. I've seen mysterious
things such as simple as unreported changes to files mysteriously being
deleted from the repo.

------
azag0
I use git often on the command line, especially for non-trivial tasks, but do
not quite understand why someone would pick it for routine committing/tree
view over a GUI. I find the ability to graphically see the state of the
working tree and the index, and being able to stage/unstage individual lines
by visual selection in a non-linear way absolutely natural. Likewise, the
ability to get a context menu for a commit in a tree view and fire a command
(rebase/branch most often) seems like something git was "built" for.

~~~
heartsucker
I spend a lot of time in the commmandline, so it makes sense for me to not use
a GUI. This alias (in ~/.gitcofig) is gold for most of the "graphical" stuff
I'd use something like SourceTree for.

    
    
        [alias]
    	lg = log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%C(bold blue)<%an>%Creset' --abbrev-commit

~~~
Zardoz84
I have these alias, plus :

    
    
        lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all

~~~
eridal
these are really good! I have this one..

    
    
      lg = log --graph --decorate --pretty=oneline --abbrev-commit

------
rollulus
My tip #20: tig [1]

[1]: [http://jonas.nitro.dk/tig/](http://jonas.nitro.dk/tig/)

~~~
ashitlerferad
gitk is great if you are outside a terminal

------
Pirate-of-SV
Since interactive rebase was mentioned I'd recommend taking a look at its
--autosquash flag and the --fixup flag of commit. With autosquash the
interactive rebase will move fixup commits to where they belong:

    
    
      git commit --fixup=<commitref>
      git rebase -i --autosquash HEAD~5

~~~
mrich
Also enable --autostash (git config --global --add rebase.autostash true) for
that workflow so that dirty files do not get in the way.

------
jdudek
My recommendation: configure the shell prompt (add __git_ps1 to $PS1), this
saves a ton of time and makes it much easier to understand what is going on.
Especially recommended for beginners (but obviously not limited to).

~~~
Zardoz84
Use fish shell and setup it to use the git prompt. Far better that bash +
__git_ps1

------
i_have_to_speak
Mandatory xkcd reference: [https://xkcd.com/1597/](https://xkcd.com/1597/)

~~~
collyw
So true

------
egjerlow
For vimmers: [https://github.com/tpope/vim-
fugitive](https://github.com/tpope/vim-fugitive) is awesome, especially for
only adding only parts of a file to a commit.

~~~
mnsc
"fu git i've" is yoda speek for the common scenario "f-ed up git I have"

------
notzorbo3
Site is non-responsive for me. Cached link:

[http://webcache.googleusercontent.com/search?q=cache:04x449v...](http://webcache.googleusercontent.com/search?q=cache:04x449vvRhkJ:www.alexkras.com/19-git-
tips-for-everyday-use/&num=1&client=ubuntu&hl=en&gl=nl&strip=1&vwsrc=0)

------
rndstr

        git checkout -
    

Switches to the previously checked out branch.

~~~
fbr
More generally "-" is an alias for the previous branch, so it can be used in
other commands as well (ex: git merge -)

------
cornstalks
I hope I'm not the only one who thinks that "Update README file" is a poor
commit message. It's overly nondescript. A better commit message would be
"Update README install instructions" or "Fix README links to dependencies" or
anything else that better describes what about the README file was updated.

------
endgame
My #1 git tip to anyone who will listen: use magit. Having the options for
each command within easy reach makes getting git to do the right thing so much
easier, and the UI feels very emacs.

[https://github.com/magit/magit](https://github.com/magit/magit)

~~~
swah
A golang+termbox clone of this would be great...

(Of course, parsing text is a joy with Emacs/Lisp and a PITA in Go).

------
kevindeasis
For git commit messages. I've began liking to initiate or end a statement with
stuff like these:

¯\\_(ツ)_/¯

( ͡° ͜ʖ ͡°)

(ง'̀-'́)ง

(ノಠ益ಠ)ノ彡┻━┻

(ﾟ∀ﾟ)

ಠ_ಠ

How do you guys feel about these in git commit messages?

~~~
pavel_lishin
If they're relevant to the code change ("Not sure what I did, but the tests
are passing now ¯\\_(ツ)_/¯", "Removing production usernames and passwords from
front-end config files, MIKE ಠ_ಠ"), it's fine.

If I see a commit that's just "¯\\_(ツ)_/¯", I will force-push over it, don't
you even think about it.

------
ivan_ah
At my old job I had to do a major cleanup of a git repo with dozens of old
branches. I got really good with the `git log` command. Here my alias form my
~/.gitconfig that shows author, branches, and remotes in a colorful manner:

    
    
        [alias]
            ll = log --graph --oneline  --decorate --date=short --all --pretty=format:'%ad %h %Cgreen%an %Cred%d %Creset%s'
    

With this you have a pretty good picture of what's going on accross all
branches.

~~~
kmfrk
Can you provide an example of the output?

~~~
ivan_ah
Sorry for the delay, the main idea is to show all the branches on the
different remotes:

    
    
        * 2016-04-11 86f68c3 Ivan Savov  (HEAD, origin/bugfix/math_valign, bugfix/math_valign) Better solution to 
        | * 2016-01-20 df77345 Ivan Savov  (origin/miniref, miniref) Customizations necessary for no BS math render
        |/
        * 2016-04-07 364619f Michael Hartl  (upstream/stable, upstream/master, origin/master, origin/HEAD, master) Change to bigger line height for EPUB/MOBI
        * 2016-04-07 92952da Michael Hartl  Bump version
        *   2016-04-07 6a56c24 Michael Hartl  Merge pull request #152 from jackkinsella/patch-2
        |\
        | * 2016-03-23 216d410 Jack Kinsella  softcover check compatible with brew
        * |   2016-04-07 d792d4b Michael Hartl  Merge branch 'minireference-feature/math_valign'
        |\ \
        | * \   2016-04-07 5fa560e Michael Hartl  Merge branch 'feature/math_valign' of https://github.com/minireference/softcover into minireference-feature/math_valign
        | |\ \
        | | |/
        | |/|
        | | * 2016-01-31 77a4e5e Ivan Savov  (origin/feature/math_valign, feature/math_valign) Set veritcal-align for better looking inline math
        * | | 2016-04-07 a369139 Michael Hartl  Update README
        |/ /
        * | 2016-03-21 0e94095 Michael Hartl  Bump version number
        * | 2016-03-21 a5fbc82 Michael Hartl  Reuse menu headings in MOBI ToC
        * |   2016-03-21 fadd558 Michael Hartl  Merge branch 'master' of https://github.com/softcover/softcover
        |\ \
        | |/
        | * 2016-03-16 60dc7c9 Nick Merwin  (tag: v1.2.5) added exercise generator for course chapters
        * | 2016-03-12 fe2f844 Michael Hartl  Lower the EPUB/MOBI line height
        |/
        * 2016-03-10 bba610b Michael Hartl  Make anal changes
        * 2016-03-10 c9bad17 Michael Hartl  (tag: v1.2.4) Bump version number
        * 2016-03-10 8edf40a Michael Hartl  Add symbols for euros and pounds

------
K0nserv
Great set of tips. Unfortunately I find that so many post that suggest rebase
recommend against force pushing. This takes a lot of the power away from
rebase/amend. So much does this happen that is wrote a blog post titled "You
should force push more"[0].

0: [https://hugotunius.se/2014/09/08/you-should-force-push-
more....](https://hugotunius.se/2014/09/08/you-should-force-push-more.html)

~~~
friendzis
My _current_ understanding is that... "it depends". I like that you identified
ground rules/preconditions for aggressive force-pushing.

Imagine a scenario for a large team (think kernel). Chat logs of a team
developing some feature look something like:

A: Ok, I have finished with issue1, check out commit abcd1 B: Hm, does not
work for me. Looks like race condition in foo.c, fixed in abce2. Going to
sleep. C: You broke init_foo(), reverted in qwer3 A: Ok, modified init_bar()
works on my machine, check dvor4 C: LGTM

Yet release branch contains all those commits squashed into abcd1. Now person
B (or anyone else) has no idea whether which versions of init_foo() and
init_bar() work on their machine and what to fix.

We sometimes tend to forget (and tools like github/gitlab help with that) that
not only git, but the whole workflow might be distributed and changing history
in one place might desync it with other places. I think that unless all that
history is absolutely unnecessary, e.g. done by a single developer, is
extremely well tested, contains loads of "oops" commits, history should not be
messed with. That's why all the warnings: git cannot manage all the references
to history

------
BerislavLopac
My favourite tip for commit messages: write them as if you would explain
someone how to do what was done in the commit. So, instead of "fixed a bug"
use "replace datetime object with date". It can be more abstract for larger
commits (e.g. "refactor payments"), but it should be roughly analogue to what
you would write to a ticket title to the same effect.

------
daurnimator
My must have: pre-commit unit tests. See
[http://daurnimator.com/post/134519891749/testing-pre-
commit-...](http://daurnimator.com/post/134519891749/testing-pre-commit-with-
git)

~~~
exDM69
I usually rely on travis-ci to do this after I've committed and pushed to a
branch (and only merge back when I get a green result, this is shown neatly in
the Github UI).

A pre-commit hook probably works fine if your tests run in a few seconds. But
in one of my projects, tests run for 10+ minutes and I want to get a test run
on debug and release builds with a few different compiler versions. That's
about 50 minutes of CPU time (but embarassingly parallelizable, although I
typically don't do that). I don't want to have to wait for this to happen
before every commit (not all of which even require testing, e.g. README
commits).

~~~
daurnimator
Yeah I only run the unit tests against my current locally installed packages.

Via travis I then run a full matrix.

------
LaFolle
Talking of commit message styling, Antirez (of Redis fame) also has a say.
[http://antirez.com/news/90](http://antirez.com/news/90)

------
xavhan
love this one :

    
    
        git diff --name-only | uniq | xargs $EDITOR
    

(opens all modified files)

and this one to open files with conflicts

    
    
        git diff --name-only --diff-filter=U | uniq  | xargs $EDITOR

~~~
Zardoz84
List the files with changes

    
    
        git diff --stat 
    

And git merge-tool & git diff-tool So I can use kdiff3 when I have merge
conflicts.

------
aaossa
Am I the only one who's strugling to see the website? My Phone is having a bad
time trying to show it (Windows Phone, Internet Explorer)

~~~
miguelrochefort
Works fine on mine (Windows Phone 10, Edge).

------
chris_wot
I seriously must be doing something wrong, but when I'm doing an interactive
rebase, if it stops due to a merge conflict I sometimes find I need to tweak
other files, and to add the files to git I find I do the following:

    
    
      git add $(git diff --name-only)
    

Am I wrong, or is this the right way of doing this?

~~~
wickedshimmy

      git add -u

~~~
chris_wot
Awesome :-) I guess I need to re-read the git man pages yet again. There's
also git add -A which I can use if I add a new file.

------
ozim
I work with git daily for couple years and I find it quite tiring to follow
git branches/commits in command line.

I rather use Git Extensions on windows and on mac Git Kraken. For beginners I
think it would be better to use GUI tools.

~~~
edejong
For experienced users, I do agree wholeheartedly. However, to learn how and
why git works, it is much more intuitive to work from the command line for a
while. For example, you can browse the .git directory, see how refs work,
browse through the logs, etc. etc.

Another reason why I advice learning the command line interface first is that
it is the most versatile, so it's helpful to be able to fall back to it when
necessary. Every GUI tool I've seen so far lacks a feature or two.

~~~
ozim
For learning what 'rebase', 'merge', 'sqush', 'git fetch', 'git pull' does it
is nice to have a GUI. Command line on the other hand is usefull to restore
lost commits with 'git log' and 'git reset' and I find it quite advanced
topic. I think all basic commands are all in GUIS so those that I listed in
first line.

------
pbreit
I'm still not even quite sure how to a) discard edits that I've made but not
added/committed yet and b) delete something from a repo that I added
accidentally.

~~~
rwmj

        git checkout somefile
    

will discard edits which you've not added to the index. This command is
destructive of course.

    
    
        git rm -f somefile
    

will delete a file from the repo (you then have to commit the change). If you
want to permanently delete a file, including from history, eg because it
contains a password, that's a bit more difficult, but possible in some
circumstances.

------
akavel
I'm collecting my personal notes/tips at: [https://gingkoapp.com/git-
notes](https://gingkoapp.com/git-notes)

------
michaelmcmillan
I never recall the command, but it lives in my bash history somewhere. Running
your test suite over a series of commits can be very handy.

~~~
wickedshimmy
Something like

    
    
      (set -e; git rev-list --reverse upstream.. | while read r; do git checkout -q $r && make check; done)
    

(Aped from the very excellent [http://blog.extracheese.org/2010/12/rebase-is-
safe.html](http://blog.extracheese.org/2010/12/rebase-is-safe.html))

------
educar
git log --format=%ae | sort | uniq -c | sort -nr

------
knorker
"Table of contents"

------
the_common_man
git reflog is my favorite

~~~
pvinis
I used reflog for the first time a few days ago. I rebased a branch, and
somewhere i messed up the conflict resolution, so I wanted to undo the rebase.
It was surprisingly easy!

~~~
majewsky
reflog is one of these things where you think "that would have been awesome to
have" in hindsight.

In 2009 or so, I was using git-svn on the KDE SVN. I was preparing a major
refactoring of Kolf in a local branch (about 60 commits with 10000 lines
changed), and pushed it to the SVN once I was satisfied with it.

Unfortunately, the 20th-or-so commit failed because a SVN pre-commit hook
rejected it (there were some DOS line-endings in a source file that I
imported). At that time, git-svn was (AFAIR) already prepared to handle a
failing SVN pre-commit hook on the _first_ commit (e.g. when authorization is
missing or stuff like that), but not somewhere in the middle.

The end result was that my working copy, my index, and my master branch was
completely trashed. And I didn't have a backup... Luckily, the tip commit of
my feature branch had not yet been packed, so a clever grep on .git/objects
found it, and I could recover my pre-push state.

Since then, reflog has always been enabled on my systems. Luckily, I haven't
needed it since.

------
thiht
Wow, I had no idea git bisect was so easy to use

------
known
Brilliant tips

