What pro tips do you use when working with Git?

Not so long ago after I learned the ropes of Git, what got me curious was magic trick developers would do :slight_smile: to manage changes and commit history.

On top of basics[1], what other Git commands/options[2] do you think you can level up with?


  1. Basics such as Git checkout, branch, status, log, add, commit, push, pull, remote, fetch ↩︎

  2. For example, tricks you don’t have to log into web interface ↩︎

2 Likes

On an update script for a game I like doing reset --hard and pull --rebase

I like the idea of resetting any local changes and pulling in any updates from the source as-is, but I never had any flags for that and git pulls just always worked. I found the hard and rebase flags on an unrelated troubleshooting post and they sounded cool :stuck_out_tongue:

4 Likes
git commit --amend -m "update" .
3 Likes

Joking aside, I recently learned that I can delete a branch on a remote (e.g. github) from my local repo on my computer (so I don’t have to log in from a web browser):

git push -d remote_name remote_branch
4 Likes

git/contrib/completion/git-prompt.sh at master · git/git · GitHub

2 Likes

The git stash command is useful to know.
You can stash changes to allow a git pull to work then unstash your changes,

4 Likes

I’d love that flexibility of keeping changes aside and staging them when needed.

1 Like

Here are some which I find very useful.

# Interactively choose which files / part of files to add to the
# index. Pretty useful if you like to double check what code you 
# are committing.
$ git add -p
$ git add -p src/

# Also works when stashing changes.
$ git stash -p

# Instead of using `-m` do not provide a message. Git will open
# the default text editor where you can type the commit message. 
# The text editor will also show which files are going to be committed
# to which branch, so no need to run git status.
$ git commit

# When wanting to commit all changes in a directory, just use commit
# instead of doing a add + commit.
$ git commit src/

# Apply changes of an existing commit to the current branch.
$ git cherry-pick "$COMMIT"

# Revert the changes of a commit.
$ git revert "$COMMIT"

# Interactively manipulate the history of the last 10 commits. Drop,
# merge, edit or reorder commits.
$ git rebase -i HEAD~10

# Show the git history including the changes made by commits.
$ git log -p
3 Likes

I have a GUI tool that I wrote and use to interact with source code systems.
It supports git, subversion (svn) and partitially murcurial (hg).

It uses that stash command to make git pull reliable as one if its value adds.

You can see its home page here https://scm-workbench.barrys-emacs.org/
and I maintain it in copr here: barryascott/tools Copr

As I develop on Fedora, Windows and macOS my tools also run on all of them.
I maintain binary install kits for macOS and Windows.

5 Likes

Another thing that is useful to configure is commit signatures. If you are already using ssh keys for authentication to the git remote its pretty simple to reuse them for signing commits. Just add the following lines to your git config (~/.gitconfig or ~/.config/git/config):

[user]
        email = ...
        name = ...
        signingKey = ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBOsxcpis76VmY0xfhwN7ZEC/Ud16Nes+eoWHZtHpEDg # <- place your public key here (`$ cat .ssh/id_ed25519.pub`)
[gpg]
        format = ssh
[commit]
        gpgSign = true

Its also possible to use gpg keys for signing, if you prefer gpg or are using bitbucket (which doesn’t support ssh key signatures) see the git documentation. After adding the git configuration go to github / gitea / gitlab and add your ssh key as signing key. Now your commits will have the verified badge next to them.

Without signatures its impossible for people to say for sure that you are the person that created the commit. Its very simple to create a commit with the credentials of another person:

$ git commit --author="John Doe <john@doe.com>"
5 Likes

I guess the other command I use a lot (via scm workbench) is git rebase.

That is how I reword commit messages, squish commits together and drop commits before git pushing them.

2 Likes

That git config is really handy working with projects in various places in Fedora Project and other upstream repos. Thanks a million.

2 Likes

There is a Git (and other VCS) integration plugin in KDE Dolphin, which is disabled by default. Enable it, and then Dolphin will show the state of files and folders in the local Git repository. The right-click menu also allows some basic Git operations.

1 Like

Good to know. I use Kate. The Dolphin (and Konsole) is built-in.

There’s also a shortcut for that: git pull --rebase --autostash

2 Likes

I have a few git log variants that come in handy, taken from different places:

[alias]
    lg = !"git lg1"
    lg1 = !"git lg1-specific --all"
    lgs1 = !"git lg1-specific --all --simplify-by-decoration"
    lg2 = !"git lg2-specific --all"
    lgs2 = !"git lg2-specific --all --simplify-by-decoration"
    lg3 = !"git lg3-specific --all"
    lgs3 = !"git lg3-specific --all --simplify-by-decoration"

    lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'
    lg2-specific = 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(auto)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
    lg3-specific = 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 cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n''          %C(white)%s%C(reset)%n''          %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)'

The git-worktree command is very very useful when one is working on different branches simultaneously. For example, if I’m writing a new quick doc and also reviewing one, I can have two worktrees and not have to keep switching between the two branches in one checkout of the folder:

https://git-scm.com/docs/git-worktree


For vim users, fugitive is really good:


There’s pre-commit that is very useful to run hooks before committing.

https://pre-commit.com/

For Python code, for example, we use pre-commit to format our code before it can be committed:

(An idea could be to add a pre-commit hook for docs repos that can run the formatter and other tweaks before commits)


I use it along with git remote prune <remote>, which removes local copies of branches that don’t exist on the remote to clean up the local checkout a little.

5 Likes

Since we’re on Fedora’s discourse: Have something like

[includeIf "gitdir:~/fedora/"]
        path = ~/.config/git/config.fedora

in your global git config (e.g. in ~/.config/git/config), and put all the things which you want for your Fedora work in ~/.config/git/config.fedora (assuming you work in repo clones below ~/fedora/), for example:

[alias]
        fedtag = ! git tag $(fedpkg verrel)
[user]
        email = mjg@fedoraproject.org
[push]
        default = simple

If you feel fancy, you can make your life easier with dist-git: fetch via https (faster) and push via ssh; add your fork remotes with a URL like dist-git:mjg/rpms/forkedproject:

# ssh for pushes only
[url "https://src.fedoraproject.org/"]
        insteadOf = dist-git:
[url "ssh://mjg@pkgs.fedoraproject.org/"]
        pushinsteadOf = dist-git:
# rewrite "fedpkg clone" generated config
[url "https://src.fedoraproject.org/"]
        insteadOf = ssh://mjg@pkgs.fedoraproject.org/
[url "ssh://mjg@pkgs.fedoraproject.org/"]
        pushinsteadOf = ssh://mjg@pkgs.fedoraproject.org/
# convenience for my forks
[url "https://src.fedoraproject.org/forks/mjg/"]
        insteadOf = dist-git:mjg/
[url "ssh://mjg@pkgs.fedoraproject.org/forks/mjg/"]
        pushinsteadOf = dist-git:mjg/

Since I did not include rpms in the substitution you can use it for requests, flatpaks etc. also.

5 Likes
git log --oneline --decorate --graph --boundary <branch1>...<branch2>

is also useful to compare branches (local or remote)

4 Likes

I do use that a lot, but I haven’t got it down as an alias in gitconfig. Perhaps it’s time to add a lgdiff alias :slight_smile:

1 Like

This is excellent @job79, I had most of those in my ~/.gitconfig, but was missing the [commit] stanza.

Also, the value for signingKey can be the (full path to the) filename containing your SSH private key.

Here’s another ~/.gitconfig trick I learned a few years ago. This uses the Fedora package diff-so-fancy to perform granular highlighting of git diff. Change colors to suit your taste:

[color "diff-highlight"]
	oldNormal = red bold
	oldHighlight = red bold 52
	newNormal = green bold
	newHighlight = green bold 22
[color "diff"]
	meta = yellow
	frag = magenta bold
	commit = yellow bold
	old = red bold
	new = green bold
	whitespace = red reverse
[diff-so-fancy]
	changeHunkIndicators = false
	stripLeadingSymbols = false
3 Likes