I've seen more stash accidents than any other kind with git. Stashing is more dangerous than committing or branching, and to me it doesn't seem to provide any advantages... do people actually find stashing easier than branching? Is it just because when you branch you have to name it, and that causes friction? I stay away from stash.<p>Right from the man page: "If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms."<p><a href="https://git-scm.com/docs/git-stash" rel="nofollow">https://git-scm.com/docs/git-stash</a><p>--<p>I do like shorty. My version:<p><pre><code> alias gits='git status -sb'
</code></pre>
--<p>My next fave is rebase the current branch against it's upstream branch point:<p><pre><code> [alias]
rearrange = "!git rebase -i $(git merge-base HEAD @{u})"
</code></pre>
git rearrange ftw.
Some of my aliases, first some basic shortcuts:<p><pre><code> freshen = commit --amend --no-edit --date=now
cont = rebase --continue
br = branch --column
recent = branch --sort=committerdate
idiff = diff --cached
ff = merge --ff-only
co = checkout
</code></pre>
Show what's left to do in an interactive rebase:<p><pre><code> todo = !cat `git rev-parse --git-dir`/rebase-merge/git-rebase-todo
</code></pre>
Set tracking to to origin/<the same branch name><p><pre><code> upstream = !zsh -c 'git branch --set-upstream-to=origin/$(git symbolic-ref --short HEAD) $(git symbolic-ref --short HEAD)'</code></pre>
I use this to swap my work to home e-mail or vice-versa if I've got it wrong. Need to specify an initial commit.<p><pre><code> allmine = filter-branch --env-filter 'GIT_COMMITTER_EMAIL=my@email.com GIT_AUTHOR_EMAIL=my@email.com'
vim = "!gvim `git ls-files -m`"</code></pre>
A few that weren't mentioned below:<p><pre><code> git alias start 'checkout @{u} -B'
</code></pre>
All my branches track origin/master (rather than local master), which makes it easy to git push / git pull without extra arguments. This will checkout a new branch from whatever the current branch is tracking. Usage: `git start my-new-feature`<p><pre><code> git alias track 'track = branch --set-upstream-to'
</code></pre>
Sets up your current branch to track some other branch. Usage: `git track origin/master`.<p><pre><code> git alias gcbr 'gcbr = !git branch --no-track --no-color --merged | sed 's/[ *]*//' | grep -v master | xargs -n1 git branch -d &> /dev/null || exit 0'
</code></pre>
"Garbage Collect BRanches" will delete any branches which are already merged into your current branch (excluding master). Basically, any branch which is "safe" to delete. (This one has been handed down through the ages; I initially found it on the skeleton dotfiles when I started working at Facebook. Thanks, whoever!)
I'm no Git wizard, but switching from "merge" to "rebase" and from "add <file>" to "add -p" cleaned up my repos quite a bit.
> so it’s good practice to create an empty commit as your repository root<p>While I'm aware of issues with rebasing the root commit, I've never heard this advice before and it seems unnecessary.
> git it and empty root commit<p>Why doesn't git init does this by default? It would be nice if every repo had an empty root commit (with no author, date,... so it has the same commit hash), then every two repos would have a common commit. Semantically it would mean that repos would be just specific branches of a hypotetical large repo.
This doesn't even look like I wrote it, but I thought I did and use it all the time: "What was that (private) branch I worked on a few weeks ago?"<p>Just put this shell script in /usr/local/bin or wherever as "git-branch-dates"<p><pre><code> git branch-dates
#!/bin/bash
for k in `git branch|perl -pe s/^..//`;do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k|head -n 1`\\t$k;done|sort -r</code></pre>
<p><pre><code> alias such=git
alias very=git
alias wow='git status'
$ wow
$ such commit
$ very push
</code></pre>
<a href="https://twitter.com/chris__martin/status/420992421673988096?lang=en" rel="nofollow">https://twitter.com/chris__martin/status/420992421673988096?...</a>
My personal favorite two:<p><pre><code> jschroeder@omniscience:~$ git config alias.up
pull --rebase
jschroeder@omniscience:~$ git config alias.down
push
</code></pre>
They can be used thusly:<p><pre><code> git up && git down</code></pre>
I like the `git grog` command, I might actually use that.<p>The idea of `git please` is not bad but it made me wonder if it could be possible to go even further.. a variant on --force that only force-pushes IF NOT ONE HAS PULLED YET.<p>I can see why this wouldn't be built into git core however, as it's quite stateful and depends on tracking other people's fetches, which probably isn't easy.
one thing i wish git would do would be to allow me to specify default options for certain aliases. for example, I quite like the `--short --branch` format of git status. but I can't do this:<p><pre><code> [alias]
status = "status -sb"
</code></pre>
because git just ignores those. i am then forced to setup non-standard commands just to bend git to my will.<p>in some cases, there are distinct `git-config` options I can set to get the right behavior, but that's way less flexible since stuff like `--force-with-lease` don't have their own config options.<p>the rationale behind this is, according to the git-config manpage, that "To avoid confusion and troubles with script usage, aliases that hide existing git commands are ignored". but then there's --porcelain for that, so i don't understand that limitation.<p>sigh.
> If in doubt, the long one (git staaash) will always restore your worktree to what looks like a fresh clone of your repository.<p>Not necessarily. This depends on what branch you're on as well as whether or not it's up to date with the remote.
My most useful bash alias (when you go back to master and want to start at the most up to date everything before creating a new branch):<p><pre><code> alias grm="git fetch origin && git reset --hard origin/master"</code></pre>
My two favourite aliases :<p><pre><code> mo = ls-files -m
lol = log --oneline --decorate --graph
</code></pre>
`git mo tests/` gets you modified files for the tests folder.<p>`git lol` I think as the command line version of gitk
Nothing esoteric, but I advise every person I teach git about to put this in their .bashrc:<p><pre><code> alias s='git status'
alias l='git log --graph --oneline --decorate --all --show-signature'
alias d='git diff'
alias dc='git diff --cached'
alias c='git commit -m'
alias ca='git commit -am'
alias a='git add -p'
alias u='git checkout -p'
</code></pre>
These probably saved me hours of typing by now. Especially `l` I think should be canon.
I'm still getting to know Git, and I appreciate articles like this as they touch on approaches to Git that have benefits in the real world, but I can't help but feel that version control tools should be simpler.<p>Does anyone have any experience with version control tools that have worked out simpler to use than Git? I've heard good things about Darcs before (aside from its performance issues, which projects like Pijul are designed to address), are there any other tools that are worth investigating?
<i>The first commit of a repository can not be rebased like regular commits</i><p>That's not necessarily true. This can be done with:<p><pre><code> git rebase -i --root</code></pre>
Nice list! I'll adapt some for my git workflow.<p>Here's some that I've created or collected over the years, in case anyone finds this useful:<p><a href="https://github.com/randombk/randombk-dotfiles/blob/master/master-main/.gitconfig" rel="nofollow">https://github.com/randombk/randombk-dotfiles/blob/master/ma...</a>
For every repo I fork I usually add a remote named upstream pointing to the original.<p>So then, whenever I need to get my copy up to date with upstream it's:<p><pre><code> update = !git fetch upstream && git merge upstream/master'
</code></pre>
It's probably easily changed to make the branch configurable, but I have only ever needed this with master.
A couple of aliases I use all the time:<p><pre><code> [alias]
graph = log --oneline --decorate --graph --all
copy-logs-since = !git log --reverse --format=%B "$1".. | pbcopy
</code></pre>
`graph` is similar to `grog` in the article. `git copy-logs-since <tag>` copies log messages since the tag, which I use for release notes. Very handy.
> git commend quietly tacks any staged files onto the last commit you created, re-using your existing commit message. So as long as you haven’t pushed yet, no-one will be the wiser.<p>Well, they might notice that the author and committer dates don't match, but you can add "--reset-author" to <i>really</i> make this undetectable.
I like "git ready":<p><pre><code> ready = !git checkout master && git fetch -p && git merge --ff-only
</code></pre>
The use case is for when you're done with a particular feature branch and ready to start something new. It puts you back on master and updates it in a safe way.
<p><pre><code> git diff origin/master -- test.file
</code></pre>
It will show you a diff of a file between the master branch of remote origin and your local branch. I use it way more than I can think of.
Didn't know about those stash options. I've always used 'git stash save -u' to bring along the untracked files in the stash, that's the more common scenario.