Git 2.19.0 released
lwn.net
lwn.net
What is your favourite git shortcut or feature!?
Stash has to be my favorite (especially with "-u" AKA "include untracked").
I'm generally very comfortable doing even advanced stuff in git, but still get paranoid about some things. Especially when I'm trying to troubleshoot something for someone else.
Being able to stash away current changes in a place that is separate from any particular branch is invaluable.
I often show stash to people that make a habit of copying their entire project directory before doing something they aren't sure about (backups aren't inherently a bad idea, but that's why you push early and often).
And even better if you alias `git` to `g`!
gb for go back.
Stashes are for quick save and restore. Branches are way more powerful.
Also make a habit of saving your stashes with a meaningful label.
But yeah, like others suggest -- use branches.
Namely, I have two I need to write. One preventing master pushing, as sometimes I forget which branch I'm on if I'm all over the place. And two, preventing committing past a `wip` commit message. Arguably I shouldn't be using wip commit messages, but I prefer being able to have a "stash" per branch, of sorts. If I stashed it, I fear namespace clobbering as well as forgetting I even had a wip.
$ git config --global alias.wip
!git add --all && git commit -am 'wip'
$ git config --global alias.popwip
!git log -1 --pretty=%B | grep -q '^wip$' && git reset HEAD^ || echo 'HEAD is not a wip commit'Revsets. Oh wait, git doesn't have revsets it has the ungodly pile of shit that is gitrevisions(7)
Reifying revisions as sets and applying set combinations and predicates to these revision sets: https://www.mercurial-scm.org/repo/hg/help/revsets
It makes for flexible, reliable and readable revisions specifications.
Details: `git show <COMMIT_ID>` gives you the patch identified by COMMIT_ID. Appending ` -- somefile` narrows that patch down to only include the specified path.
The `-R` option to `git apply` tells it to apply the patch in reverse.
Thus, "undo the changes in `somefile` from this commit".
#!/bin/zsh
git push -u ${1:-origin} HEAD:"$(git symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')"
This means "push the current branch to origin (or the first argument, if specified) to a branch of the same name, when this hasn't been done before. Set origin (or the first arg) as the upstream of the local branch". Formally invoked as `git first-push [remote]`, I just alias it to `git fp`.EDIT: I've forgotten offhand whether there are actual zsh-isms here. It's probably bash compatible, but I always have zsh installed by the time this script lands on a system.
git push -u origin head
? git push -u
which does what I want since I set git config --global push.default=currentBut if you use git around me the thing I'll keep talking about is force with lease (as seen in e.g. "git push --force-with-lease"). I believe this is a specific implementation of an idea with much broader possibilities that we should see in a LOT more places.
The central idea of force-with-lease is that when I'm telling a machine that I understand all the circumstances and nevertheless I wish to proceed anyway, I should need to tell the machine what these circumstances are that I'm claiming to understand. For example I know the current state of the tree is rel-4.2.6-20180911 and I'm confident that we want to smash that, and put rel-4.2.6-20180912 there, even though that rewrites history. Then the machine can check automatically that those _are_ the circumstances and refuse to override if not.
In git the reason to have this feature is that it prevents the situation where I think rel-4.2.6-20180911 is in the branch, I'm sure I want rel-4.2.6-20180912 there, so I force that, but unfortunately while I was deciding to do that somebody else landed rel-4.2.7-20180912 and so I've ruined everything by forcefully reverting their change.
The broader idea is very widely applicable. In Puppet for example, somebody can tell the system to stop updating node-04 because "Barry found a problem with XYZ on this node, check with Barry before re-enabling". And if you try to update node-04 it will recite that blurb and refuse. But, you can force enable node-04 without reading the blurb, and worse, if meanwhile another engineer changes it to "Figured out XYZ. Definitely don't re-enable Puppet without talking to me, Sarah" you won't even know that happened, your override will take effect anyway even though you'd no chance to know you should call Sarah.
Even in non-IT systems I think this approach has great merits. Consider a railway signal system. Most of the system isn't the "signals" (which are mostly boringly simple and reliable colored lamps) but the sensors verifying that the state of the system is consistent and safe. Humans are often authorised to overrule this system in small ways when things go wrong. A sensor says it isn't sure if the motorised points at a junction are closed, so the system refuses to move signals from "Danger" for that junction. The human signaller is authorised to tell human train drivers to ignore this Danger signal and proceed, albeit it "at caution, obeying all other signals". But wouldn't it be better if the system required the humans to acknowledge specifically that they've understood the problem is that the sensor says these points aren't locked? Now the driver is thinking about the points, which might not be locked, rather than just vaguely knowing something, somewhere, is busted. Guess who is going to take a proper look at those points before driving over them now! And when the next train arrives, and the signaller tries to let it through, if in fact NOW the problem is that the points are fine but the axle counter says the previous train never left, the signaller would need to diagnose and accept this situation, not just wave through another train assuming it's the same fault because it has the same symptom (signal at danger).
(Also, I tend to use just `git log origin..` rather than spelling out `origin/master`.)
Doesn't work for me:
$ git log origin..
fatal: ambiguous argument 'origin..': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ git log origin.. --
fatal: bad revision 'origin..'Nice to see this one land. That was a pretty annoying usability problem for with the send-email command, and a barrier for people less knowledable about git using it.
diff -u <(git log -p master..fix-typos@{3}) <(git log -p master..fix-typos)
We actually have a program at my job that posts links to diffs like this in Github PRs whenever someone rebases the branch associated with the PR and force pushes it up to the remote. git log -p master..fix-typos@{3} > tmp1
git log -p master..fix-typos > tmp2
diff -u tmp1 tmp2
except that pipes are used instead of temporary files.If you make changes to your code and/or commit messages and subsequently rebase the branch, then the end-sha1-value will change (since you now have a different set of commits). If you run the same git log -p command with the new end-commit-sha1 value, then the log output will differ based on the changes you made when you rebased.
So if run a diff between the two git log -p outputs (one with the original end-commit-sha1 and the other with the new end-commit-sha1), you'll be able to see the difference between the two logs which includes the changes you made to the code and/or commit messages).
I'll definitely try it out and see how it compares to what we're doing now.