Little Things I Like to Do with Git
csswizardry.com
csswizardry.com
See https://github.com/blog/2188-git-2-9-has-been-released (section Beautiful diffs) for an example and http://blog.deveo.com/whats-new-in-git-2-11/#experimentalheu... for another similar option that I did not try yet.
For readers in a hurry, careful: `compactionHeuristic` ended up deprecated in Git 2.11 . The experimental heuristic to add to a >=2.11 .gitconfig is now `indentHeuristic`, see OP's second link :)
Thanks!
git-overview: Short report about top committers, files with most commits and most authors. Nice when you checkout a non-trivial repo for the first time.
git-onNotify: Do something (like `make`) whenever a tracked file changes. Usually used to build LaTeX and static websites.
git-randomline: Chooses a random file and a random line number there. The game is explain that single line to some fellow. Do this repeatedly to spread knowledge about a codebase.
git-tarball: Pack the repo into a tar.bz2 file.
alias co='select br in $(git recent); do git co $br; break; done'
so when I type "co" at the command prompt I get a numbered menu of branches in the order I last checked them out, and can just type a branch's number and hit return to check it out again. st git status ...
gl git log ...
gd git diff ...
gg gitg
gup git pull --rebase
gb git branch
The dots mean there are more arguments. The point is, every once in a while I analyse my shell history and add aliases for the most used commands. Looking at it now, it seems I should add aliases for `git push` and `vi Makefile`.I also have the aliases g for git, m for make, and v for vim.
gs git status
gp git push
gac git commit -am
gc git commit
gcm git commit -m
gA git add -A
gC git checkout
ga git add
gd git diff
gm git merge
gmc git merge --continue
gpu git pull
grc git rebase --continue
The only problem is that I cannot use git on anybody else's machine, the muscle memory is too strongly ingrained now. This is a common message: The program 'gs' is currently not installed. You can install it by typing:
sudo apt install ghostscript $ -gsOf course, my personal solution instead of aliases was to switch to using SourceTree.
But anyway, if someone asks for help with "how to fix my mess in git", the absolutely first thing I do is exactly `git log --graph --decorate --all --oneline`, to start finding out visually what the mess actually is.
gdc git diff --cached
gg git grep -n
gss git status -s
glo git log --oneline
gamend git commit --amend --no-editA few more I live and die by:
gf git fetch --all; git fetch --tags
gh git log --oneline --abbrev-commit --all --graph --decorateedit: yep, per git help log:
--oneline
This is a shorthand for "--pretty=oneline --abbrev-commit"
used together. alias ga='git add'
alias gb='git branch'
alias gbD='gb -D '
alias gbc='gc -b '
alias gbd='gb -d '
alias gc='git checkout'
alias gcm='git checkout master'
alias gd='git diff '
alias gdd='gd --cached'
alias gdm='gd master...'
alias ge='git grep -InE '
alias gec='git branch --remotes --contains '
alias geh='git log --all --oneline --decorate -G '
alias gei='ge -i'
alias gff='gh && gpr && gr && ghp'
alias gfm='b=$(gw) && [[ "$b" != master ]] && gcm && gpr && gfu && gr && gc $b && unset b'
alias gfr='git fetch && git rebase origin/master'
alias gfu='git fetch upstream && git merge upstream/$(gw)'
alias gh='git stash'
alias gha='gh -k'
alias ghp='gh pop'
alias ghs='gh show -p '
alias gl='git log --graph --decorate --all'
alias gll='gl --pretty=format:"%C(yellow)%h %Cred%ad %Cblue%an%Cgreen%d %Creset%s" --relative-date'
alias glll='gl --color --graph --pretty=format:'\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%C(bold blue)<%an>%Creset'\'' --abbrev-commit'
alias gp='git pull '
alias gpr='git pull origin $(gw)'
alias gps='git push'
alias gpt='gps --tags'
alias gr='git push origin $(gw)'
alias grr='git rebase -i HEAD~$(grrr | wc -l)'
alias grrr='git rev-list master..'
alias grt='gr --tags'
alias gs='git status'
alias gss='git show'
alias gu='git config --get remote.origin.url'
alias gv='git describe --abbrev --dirty --always --tags'
alias gw='git rev-parse --abbrev-ref HEAD 2>/dev/null'
alias gx='git archive --format tar --remote 'https://mikegerwitz.com/projects/git-shortmaps/about/
It creates the aliases as you do, but also includes tab completion, and only takes effect when you're in a repository path.
Alas, that is not the case with bash.
Personally, I use mostly command line git and on occasion a little bit of gitk if I get lost between all the branches. I die a little (read: a lot) inside when I have to help my team members with git and they adamantly stick to TortoiseGit. It's a prime example of the UI improving discoverability at the expense of performance (and even then the individual actions tend to get lost between all the numerous possible actions).
It is similar for committing, where checking diffs and partial adding is part of the process.
Using an IDE or GUI might help to streamline this. I do not use any, so I don't know if they do this.
Maybe I should analyse my shell history for sequences?
> That is actually an SVNism.
Yep. From the article:
> Taking the lead from SVN, I alias praise onto blame…
:)
> Are we really that afraid of hurting someone’s feelings…
I don’t do it to save peoples’ feelings: I do it because there are two separate use cases for determining the author of something—sometimes I really do not want to blame[1] someone.
1. blame — verb: feel or declare that (someone or something) is responsible for a fault or wrong.
Also, truthly, if you're looking to see who/win a line of code was authored, it's almost always because you're tracking down a problem. :)
alias gitroot='cd $(git rev-parse --show-toplevel) && echo "$_"'Basically, if you're in the directory `~/something/src/projectname/foo/com/something/bar/baz`, and want to get back up to say `~/something/src/projectname/foo`, `to foo` will do that. (Or `to oo` or `to o`; it matches the end of the name, and goes to the first match; `to ing` would go to `~/something/src/projectname/foo/com/something`).
[alias]
# Show top level repository
root = rev-parse --show-toplevel
I have found that useful over time.Since tags, branches and `HEAD` are simply pointers to commits, it's good to know that you can interchange them and commits pretty much anywhere where you can use them (other than creating/deleting tags or branches, of course).
up = !git pull --prune $@ && git submodule update --recursive
cm = !git add -A && git commit
save = !git add -A && git commit -m 'SAVEPOINT'
undo = reset HEAD~1 --mixed
amend = commit -a --amend
# Removes branches deleted from remote repo
bclean = "!f() { git branch --merged ${1-master} | grep -v " ${1-master}$" | xargs git branch -d; }; f"
# Leave current branch & do some cleanup
bdone = "!f() { git checkout ${1-master} && git up && git bclean ${1-master}; }; f" glog = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
stash-all = stash save --include-untracked
update-fork = "!f() { git pull --rebase upstream $1 && git push origin $1; }; f"Clearly the guy who came up with this cockamamie scheme was unfamiliar with Linux. :-)
+ RCS was pretty bad too; I'm using it just for illustrative purposes
> git commit -am "TMP COMMIT" > git checkout ... Once you switch back: > git reset HEAD^
and you'll undo the temporary commit and be back to where you were.
This doesn't exactly fit what you're asking for, but is an alternative workflow where you'll never need to do that.
I do git reset --soft HEAD^ so that the changes from the previous session are still staged, which is occassionally useful.
https://git-annex.branchable.com/
I don't know how the situation has changed in regards to binaries, or if this is a good suggestion, I just remember reading about git-annex when it came out a few years ago.
Some binaries can be serialized so they at least function as text files for vanilla git's benefit. I did a project where we used LibreOffice or OpenOffice and we had a hook than unzipped the contents and flattened them into text for checking in and reversed that when checking out. It worked, technically, but we lost most of the benefits of git (tiny changes would lead to changes to several binary tables which lead to incomprehensible diffs). On the other hand the same project used gnuCAD which saves its files as text -- which was awesome: we made some edits (id changes and the like mostly) with sed and awk!
The big binaries problem is the sole reason anybody buys Perforce. It's horrible, but it does handle this case, and for folks like game developers there's little alternative.
I really do wish I could use git with solid works and Cadence files. Solidworks is the worst: their files are build with some Microsoft structured file library, and contain hard-coded paths; their dreadful proprietary SCM tool understands this and edits the file while checking it out to fit it to your local machine. Aaagh!
And it's all centralized. Recently we had an internet outage for a repo hosted on github: people still got work done and collaborated, pushing to and pulling from each others' machines until we had external access restored the next day. With FB down it was a pretty productive day!
Full implementation list https://github.com/git-lfs/git-lfs/wiki/Implementations
I work on a codebase that's over 20 yrs old. A while back, I was interested to find out who had done the most commits, and what kind impact moving to git, with it's "commit early, commit often" mentality, had pushed newer players up the ranks. Suffice to say, it hadn't had as much impact as I was expecting yet.
SVN definitely aliased "blame" and "praise" to annotate, though.
https://lobste.rs/s/f0t07t/little_things_i_like_do_with_git#...
Though it can be difficult to notice an addition if it's just one or two chars.
git for-each-ref --sort=-committerdate
.. shows progress for each branch .. this makes it surprisingly easy to see which of the developers in our group (with their own branches) is pushing the codebase further ..Sorted by 'most recently touched'.
Are you trying to separate the wheat from the chaff from developers that are already in your team?
But no, Fossil's UI is like Mercurial's, and it favors merging over cherry-picking and rebasing. Their loss!
Fossil does have a cherry-pick operation, and anyways, one could trivially be constructed. Which means that rebase can also be constructed easily enough. But my impression is that the devs aren't interested in such contributions. And the heavy- vs. light-weight branching model in the UI is a big turn off even if I can deal with it at the SQL level. Fossil's push/pull model ([auto]sync everything) is also not to my liking -- sure, in a corporate environment pushing every branch is a good idea, but in an open source world it's not: I may want to push some branches to one upstream, others to another, and yet others not at all.
This is what I like about git:
- the index
- git exposes the Merkle hash tree concept at the lowest layer
- git branches and tags are just symbolic pointers to commits (see previous point)
- support for many remotes
- git is not opinionated -- if you want to use a merge-based workflow, you can, and if you want to rebase instead, you can, and if you have to use e-mail to exchange commits, you can, and so on.
I'm done with the Mercurial "you do what we say" model. A model they keep half-way reneging on, adding bookmarks (which don't work well), and histedit and rebase (why not both in one command?! "because we don't like git rebase" is the answer I imagine) (they really need to be one command!! what if in the process of rebasing you must drop commits that you know duplicate others in the new base?!).
I wish Fossil's developers saw this. But they're focused on their needs: VCS for SQLite3. Since they seem to have few topic branches, they like merging.
Conversely, since Fossil's devs refuse to be non-opinionated, I wish git's developers saw the power of SQL for VCS. It would save a ton of code C and shell code, and it would make new extensions trivial. It also would make git much more power-failure safe: since it could leave that to something like SQLite3 that does a fantastic job of it (and is very well tested, both in general and as to power failure safety).
Besides this, I wish git has branch history. That is, a single push can push multiple commits by different authors, so it would be nice if one could see who pushed what commits. This would be useful as documentation in and of itself: if you see N>1 commits pushed together and need to revert one of them, you might look at whether you need to revert the rest as well, as they might go together. (Some codebases like to push regression tests first, bug fixes after. This allows one to see that tests detect the bugs they're testing for and that corresponding bug fixes fix those bugs. If one has to revert a bug fix commit, one might have to also revert a corresponding test commit.)
Mercurial seems to give merge tools better information when rebasing too. I've had to resolve some annoying conflicts when rebasing with git, and I've cloned the repository with hg-git and done the same rebase and had it go flawlessly.
Also, don't forget the index! I adore the index in git.
Similarly, when I use go I do not miss generics despite using them quite a lot when they are available in other languages.
So based on this, I both agree and disagree with your complaint about fossil not having rebase.
However, one place where I disagree is that fossil is not just VCS for SQLite3. Its github in a single executable -- much more powerful and potentially much more important for the opensource community. In some dystopian future developers will be using fossil over tor.
I can imagine that a VCS might make merging so painless that one might not miss rebasing, but I would still prefer rebasing.