If you manage applications on Linux servers, you probably pull code over SSH several times a day. Each operation takes only a few seconds, but the friction adds up when every git log requires multiple flags, git pull stops to ask how to reconcile divergent branches, and GitHub pushes repeatedly prompt for authentication.
Most of these interruptions come from Git and GitHub CLI defaults that do not match your workflow. A few one-time configuration changes can simplify common commands, make pull behavior predictable, keep repositories maintained, and reduce repeated authentication prompts.
Both Git and the GitHub CLI (gh) support persistent settings, allowing you to apply these improvements without changing your deployment scripts or configuring every command from scratch.
How git config and gh config Store Your Settings
Before changing anything, it helps to understand where Git stores its settings. Git uses three configuration levels, with more specific settings overriding broader ones:
/etc/gitconfig # --system: every user on the server ~/.gitconfig # --global: your user, every repository /.git/config # --local: one repository only
The examples below use git config --global, so the settings apply to every repository managed by your current Linux user, including tecmint. Repository-specific settings can still override them.
The GitHub CLI (gh) stores its preferences in ~/.config/gh/config.yml and its authentication information in ~/.config/gh/hosts.yml.
These files serve different purposes: the configuration file controls CLI behavior, while the hosts file stores authentication data for GitHub accounts and hosts.
Install Git and the GitHub CLI on Linux
Git is already installed on many Linux servers, but the GitHub CLI (gh) may be missing. Install both on the example server, 192.168.122.248, using the commands for your Linux distribution.
On Ubuntu and Debian, install the packages from the configured APT repositories. The available gh version may lag behind the latest upstream release.
sudo apt update sudo apt install -y git gh
On Rocky Linux, AlmaLinux, and RHEL, Git is available through the standard repositories, but the GitHub CLI may require its official RPM repository. Add the repository and install gh as follows:
sudo dnf install -y git 'dnf-command(config-manager)' sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo sudo dnf install -y gh --repo gh-cli
Verify the installed versions before proceeding:
git --version gh --version
The examples below assume Git 2.34 or newer, which introduced background maintenance scheduling through systemd timers on Linux. Some commands and options may behave differently with older releases, so check your installed version before applying the configuration.
1. Shorten Daily Git Commands with Aliases
The first improvement is to reduce repetitive typing. Git aliases let you assign short names to frequently used commands and their options, making everyday repository checks faster.
Configure these three aliases globally:
git config --global alias.st 'status -sb' git config --global alias.lg 'log --oneline --graph --decorate -15' git config --global alias.last 'log -1 --stat'
Here is what each alias does:
struns git status -sb, showing the current branch and a compact summary of staged, unstaged, and untracked changes. When upstream tracking is configured, it also shows whether the branch is ahead of or behind its upstream.lgdisplays the last 15 commits in a compact graph, with abbreviated commit IDs, decorations such as branch names and tags, and one-line commit messages.lastshows the most recent commit and a summary of the files it changed, including insertion and deletion counts.
For example, run these commands from your application directory:
cd /var/www/app git st git lg git last
You can now check the working tree, inspect recent history, and review the latest commit without repeatedly typing long command options. Because these aliases use `–global`, they are available in every repository accessed by your current Linux user.
2. Prevent Accidental Merge Commits with pull.ff
Aliases save keystrokes, but a more disruptive problem is a git pull that stops a deployment with the error fatal: Need to specify how to reconcile divergent branches.
Modern Git displays this message when local and remote branches have diverged and no pull strategy has been configured.
On a deployment checkout, you may want Git to accept only fast-forward updates and stop if the local branch contains commits that are missing from the remote.
Configure that behavior globally:
git config --global pull.ff only git config --global fetch.prune true
These settings solve two different problems:
- pull.ff only allows git pull to update the current branch only when Git can fast-forward it. If local and remote histories have diverged, Git aborts with
fatal: Not possible to fast-forward, aborting.rather than creating a merge commit. - fetch.prune true removes stale remote-tracking references when you fetch. If a branch has been deleted on GitHub, its outdated tracking reference is removed, keeping the output of
git branch -rtidy.
If a pull fails because Git cannot fast-forward, inspect the recent history before changing anything:
git lg git status -sb
If the server contains an unexpected local commit, determine whether it should be pushed, preserved on another branch, or discarded. Do not reset or discard it blindly, especially on a production server.
git pull keeps failing during deployments, share the tip with a teammate who still has to clean up unexpected merge commits on production servers.3. Keep Large Repositories Fast with git maintenance start
The first two hacks speed up your commands, while this one speeds up Git itself. Frequently pulled repositories collect loose objects and pack files, so Git slows down over months, and an automatic git gc can start in the middle of a deploy.
The git maintenance command moves that housekeeping into scheduled background jobs, so register the repository from inside its directory:
cd /var/www/app git maintenance start
This adds the repository to maintenance.repo in your global config and creates hourly, daily, and weekly systemd user timers (or cron jobs when systemd user services aren’t available), which you can list:
systemctl --user list-timers 'git-maintenance@*'
You should see the hourly, daily, and weekly git-maintenance@ timers listed, with next-run times that differ on your server.
User timers only run while you have an active login session, so enable lingering for your user to keep the jobs running after you log out:
sudo loginctl enable-linger tecmint
4. Stop GitHub Token Prompts with gh auth setup-git
With Git itself tuned, the remaining delay comes from GitHub authentication. GitHub no longer accepts account passwords over HTTPS, so every push asks for a personal access token, while the GitHub CLI can log in once and hand that token to Git whenever it asks.
Start the login from the server:
gh auth login
Choose GitHub.com, HTTPS, and Login with a web browser, then enter the one-time code that GitHub CLI (gh) will display a one-time device code and ask you to open https://github.com/login/device on your own computer, enter the code there and authorize the request.
This method works on headless Linux servers because the browser-based authorization happens on your local computer.
gh auth setup-git
You can check what this changed in your global Git config:
git config --global --get-regexp 'credential.*'
Output:
credential.https://github.com.helper credential.https://github.com.helper !/usr/bin/gh auth git-credential credential.https://gist.github.com.helper credential.https://gist.github.com.helper !/usr/bin/gh auth git-credential
The empty helper lines look like a mistake, but they are normal because they clear any credential helper defined earlier so Git asks only gh for GitHub credentials.
5. Configure GitHub CLI Settings with gh config
Now that GitHub CLI (gh) is logged in, tune it the way you tuned Git in the first hack, since its interactive questions leave cron jobs waiting for input that never comes:
gh config set git_protocol https gh config set prompt disabled gh alias set myprs 'pr list --author "@me"' gh alias set ci 'run list --limit 5'
Here is what each setting and alias does:
git_protocol httpskeepsgh repo cloneon HTTPS, so clones use the credential helper from the previous hack.prompt disabledstopsghfrom asking interactive questions, so a command missing a required flag fails with an error instead of waiting inside a script.myprslists open pull requests you created in the current repository.cishows the last five GitHub Actions runs, so you can confirm a build passed before you pull.
Pro Tips: Review and Secure Your Git and gh Config
With all five hacks in place, run git config --list --show-origin whenever something behaves unexpectedly, because it shows every active setting next to the file it came from.
To reuse this setup, copy ~/.gitconfig and ~/.config/gh/config.yml to other servers with scp, but never hosts.yml, since on a server without a keyring gh stores your token there in plain text.
On shared servers, avoid your personal GitHub account and use a fine-grained token passed with gh auth login --with-token, limited to the repositories that server deploys, so a compromised server exposes as little as possible.
~/.config/gh directory between servers.Conclusion
You now have shorter Git commands, pulls that never create surprise merge commits, background repository maintenance, and GitHub logins that no longer interrupt your work. Each change took one command, and together they remove most of the waiting from Git work on a server.
To wrap these commands into a deploy script that pulls, checks CI, and restarts your service, our Bash Scripting for Beginners course covers variables, error handling, and exit codes.
We’d love to hear how you’ve set up Git on your servers. Which aliases do you rely on most, and do you allow gh logins on shared servers or stick to deploy keys? Feel free to post any errors in the comments.