Better Git configuration
blog.scottnonnenberg.com
blog.scottnonnenberg.com
git config --global stash.showPatch true: A recent addition to git which defaults the -p flag to `git stash show`; meaning `git stash show` shows the diff from that stash (should really be default...)
git config --global rebase.autostash true: will automatically stash and unstash the working directory before and after rebases. This makes it possible to rebase with changes in the repo.
git config --global log.decorate full: Always decorate `git log`
rebase.autoSquash true
When committing you can specify --squash=<commit> or --fixup=<commit>, `git rebase -i --autosquash` will then automatically move and mark the relevant commits in your rebase queue. Setting autosquash into your config enables it by default for all interactive rebases. user.useConfigOnly true
that's really convenient when you routinely use multiple identities on the same machine (e.g. personal and work): by default if you haven't configured an identity locally git will fallback to global, and then to guessing based on your current user and machine.useConfigOnly mandates an explicit configuration, then you can just remove any global user or email, and git will require the correct configuration of any local repository before allowing commits.
alias.original "!git show $(cat .git/rebase-apply/original-commit)"
when performing a rebase (interactive or not) it can be difficult to remember what the original intent of a specific commit is when it's mixed with conflict markers. This shows the original commit being rebased. alias.git "!git"
I regularly type "git", go do something else, remember what I wanted to do and type "git <command><return>". This makes "git git git git show" work instead of barfing.Finally
merge.tool <yourtool>
Will automatically use the specified tool when invoking "git mergetool", if you like external utilities to perform merges or conflict resolution (e.g. emerge, kdiff3, araxis, vimdiff3, meld, etc… the list of builtin tool support is accessible via "git mergetool --tool-help") git config --global pull.ff only
I can always override an individual pull invocation with either "git pull --rebase" or "git pull --no-ff", making it a conscious choice when a fast-forward pull is not possible. $ git pull
fatal: Not possible to fast-forward, aborting.The online docs mention it in Git v2.1.0: https://git-scm.com/docs/git-config/2.1.0
Rebasing is the answer, but that will of course re-sign every commit with your key. In a shared repository, I prefer creating "useless" merge commits to changing other peoples signatures.
Is there some other part of a workflow that you're inferring here that will need changing commits?
Theoretically one could devise a tool which allows each contributor to re-sign (in the correct order), but I'm not aware that any such thing exists, and it'd probably be too impractical anyway.
git push --force-with-lease
Instead of git push -f
(Obviously ideally you'd never do either, but sometimes life happens.)The advantage of the former over the latter is that it won't push if you haven't already seen the ref you're overwriting. It avoids the race condition of accidentally "push -f"ing over a commit you haven't seen.
(Why this isn't the default, I have no idea.)
hist = log --pretty=format:\"%C(yellow)%h%C(reset) %C(green)%ad%C(reset) %C(red)|%C(reset) %s %C(bold blue)[%an]%C(reset)%C(yellow)%d%C(reset)\" --graph --date=short lg2 = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%cn%Creset %Cblue(%cr)%Creset' --abbrev-commit --date=relative
Shows dates at the end, in a relative format (2 days ago, 29 hours ago, etc) and the tags/branches before the commit message. [color "status"]
added = green
changed = yellow bold
untracked = red boldImprovements and pull requests are welcome.
Here's how I wire it into my .gitconfig, which gets me the alias "git dirdiff":
[difftool "default-difftool"]
cmd = gvim -f '+next' '+execute \"DirDiff\" argv(0) argv(1)' $LOCAL $REMOTE
[difftool]
prompt = false
[alias]
difftool --dir-diff
... I like to use gvim to open new windows separate from my terminal, but if you prefer you can just use plain vim in there as well.Also, if using vim for viewing diffs, you might want to hack vim's config as well to make it look good. I like to (effectively) disable folding of lines with no diffs so I can still read the whole file- I use the shortcuts ]c (next diff) and [c (previous diff) to jump around diffs. I also like to disable editing in diff mode.
Here's my diff-related .vimrc hackage:
if &diff
set lines=60 columns=184
set foldminlines=99999
set nomodifiable
set nowrite
endif [alias]
dirdiff = difftool --dir-diff # A nice shell prompt for inside git repostories
# Shows a short status of the repository in the prompt
# Adds an alias `g=git` and makes autocomplete work
gitprompt() {
__color_bold_blue='\[$(tput bold)\]\[$(tput setaf 4)\]'
__color_white='\[$(tput sgr0)\]'
export GIT_PS1_SHOWDIRTYSTATE=true;
export GIT_PS1_SHOWSTASHSTATE=true;
export GIT_PS1_SHOWUNTRACKEDFILES=true;
export GIT_PS1_SHOWUPSTREAM="auto";
export GIT_PS1_SHOWCOLORHINTS=true;
. /usr/lib/git-core/git-sh-prompt;
local ps1_start="$__color_bold_blue\w"
local ps1_end="$__color_bold_blue \\$ $__color_white"
local git_string=" (%s$__color_bold_blue)"
export PROMPT_COMMAND="__git_ps1 \"$ps1_start\" \"$ps1_end\" \"$git_string\""
# Short alias for git stuff
alias g=git
# Make autocomplete also work fo the `g` alias
eval $(complete -p git | sed 's/git$/g/g')
}
So I have this in my `.bashrc` and when I want my bash to get a handy Git prompt I type `gitprompt`.You do need the file `git-sh-prompt` which should come with git, for me it's located in `/usr/lib/git-core/git-sh-prompt`. It's also available here:
https://github.com/git/git/blob/master/contrib/completion/gi...
Which is not to dismiss these: Using magit involves its own cognitive load.
What is the big deal about creating a merge commit? It that because you only merge in `origin` (wherever that lives)?
The two mistaken scenarios I run into the most are:
1. `git pull` when I'm not in the right branch, which will want to do a merge.
2. When I have commit access on the master branch, and I do a `git merge branch` when that branch hasn't been properly rebased on master. My preference is no merge commit here, so I like that Git can catch this.
If you are not changing history, then merge commit cause no harm at all. You've got to be a bit careful about reverts and again choosing the correct side of the history, though.
IMHO, the rebasing style is great when you are working with a group that understands how git is working under the hood. As long as they don't do anything to break stuff, then it's very nice. If you are working with a team which a bit more laissez fair, then merge commits are generally safer -- just make sure to tell then never to change history (rebase, force push, etc).
If you mix the two, you will be spending the odd afternoon piecing your git repository's history together by hand. It is seriously not fun.
As an alternative to git's aliases: if you're sick of typing `git' all the time, feel free to adapt this little script to suit your needs (allowing you to type e.g. `a' instead of `git add' and such, with tab completion):
https://gitlab.com/mikegerwitz/git-shortmapsMaybe this is simply not what Git is made for and I should use Git from my NextCloud folder to have my data safe on a server?
Git feels so local and thus vulnerable to theft, breakage, power outages etc.
When done, clean up the history[1], push to a different "real" branch for review. Delete wip-* branch.
Unless people have actively checked out your branch locally they shouldn't have any "mess" on their end. (They'll have a remote branch listed by "git branch -r", but all of those can be cleaned up periodically with a "git prune ...".)
I haven't heard any complaints so far. (I've been doing it this way for 4+ years, I think.)
[1] I usually find that it's easier to split/clean up after the feature is almost completely done and ready for review. When I'm "in the zone" I don't want to have to suddenly switch to the "cleaning up history" mode.
You seem to be hung-up on commits or have an inexplicable aversion (IMO) to committing to a private, expendable branch. Git made branching cheap and easy by design - you can go crazy on your private 'backup' branches without having to add detailed commit messages. When you are happy, you can rebase or squash merge into the 'real' branch with proper commit messages and delete the backup branch. This will not create a mess for collaborators or your Git history (after you've deleted the ephemeral branches).
As a matter of fact, you could create an alias for 'git sync' that does the above in the background, if you find the individual steps too tedious to manually type in.
git push backup my-new-branchHowever, I recommend you use a separate tool for backups and syncing than the tool you use for version control. For example, you could use Rsync to push the files -- both the .git folder and your source code files -- to a remote server, and then pull them down on another computer. Not only will you only be committing for actual commits, but you can also save the state of your repository and continue working on it later; you could stage certain files and not commit them, sync your .git folder to another machine, then have those same files staged but not committed.
Git doesn't check validity of commit hashes by default: https://groups.google.com/forum/#!topic/binary-transparency/...
IIRC, the jquery repo was an example of one with a bad object hash.
The fsckObjects settings are entirely separate from the SHA. They are about syntactic and semantic rules in the objects themselves (e.g., well-formatted committer name/dates, tree filenames that don't contain "/", etc).
Most of the development tools I use on a regular basis tend to be extremely customizable, and I regard that as a Good Thing.
I can see it both ways. I'll choose customization, but I wouldn't fault someone for expecting a good out-of-box setup.
My main editors are Vim and VS Code, both of which I find perfectly usable OOTB.
Now, I always merge with no fast-forward because it creates a commit for the merge that you can revert.
git merge --no-ff
Then, I always pull with rebase... That will apply your changes on top of the remote ones. It may lead to conflicts but it leads to a log with less branches. git pull --rebase
The merge/diff tool I use is p4diff, which comes with P4V (Perforce visual client) and is free.To explore the git log, I use tig. https://github.com/jonas/tig
It is a curses interface to git. Screenshot: https://atlassianblog.wpengine.com/wp-content/uploads/tig-2....
Link: https://github.com/pstadler/keybase-gpg-github
Discussion on HN: https://news.ycombinator.com/item?id=12289481
So I can just e.g. type "g ws" to tell [g]it to give me the [w]orking tree [s]tatus. Seeing people actually type "git status" is just painful.
The ones I find myself using most are 'gru' for git remote update, and 'gka' for "gitk --all -500 &". (The -500 is there to prevent my laptop dying when I run gitk with --all on the Linux kernel repo without second thought...)
Now you could decide to systematize the "grammar" of your shortcuts somehow, and, well... it's definitely an idea people have had before. ;)
https://magit.vc/screenshots/popup-diff.png
Not an Emacs fanboy, by any means: I use Spacemacs. Magit is objectively excellent, though.
[alias]
wdiff = "diff --color-words" $ git config color.diff always