Mirai Kumiko's website

Mastering Git

Staging

Stage all files git add -A and unstage git restore .

Commit

To immediately commit all changed files git commit -am "Commit message"

Change last commit git commit --amend. You can quickly rewrite a commit without editor git commit --amend --no-edit

Restore file from specific commit git restore -s abcd123 file.txt

Diff

Show the state of a file in a specific commit git show abcd123 file.c

Show the difference between two commits git diff abcd123..efgh123

Log

Show last five commits git log -5

Show history of changes in patch format git log -p

Show branch tree of commits git log --pretty=oneline --graph

Stashing

You can hide your raw work with the git stash command, git stash list to show the stashes and git stash apply to apply the last stash, or git stash apply stash@{2} to apply stash by its index.

Search for a keyword in whole project git grep -n myClass

Display files with count of matching git grep --count myClass

Display commits which contains keyword git log -S ZLIB_BUF_MAX --oneline

By the way, you can specify the path to the directory in which you want to search as the last argument.

Show how the function git_deflate_bound() in the file zlib.c evolved over time git log -L :git_deflate_bound:zlib.c

Branching

git pull = git fetch + git merge

git switch -c = git branch + git switch

Process of integration feature branch:

1git switch main
2git pull origin main
3git merge feature-branch-name
4git push origin main

Tags

Tags usually calls as v1.0.0 where numbers signify major.minor.patch

major β€” Breaking changes πŸ’₯
minor β€” New features ✨
patch β€” Bug fixes πŸ”§

There are types of pre-release versions:

alpha β€” raw version of the build
beta β€” testing version of the build
rc β€” release candidate or nearly finished release

v1.0.0-alpha < v1.0.0-beta < v1.0.0-rc < v1.0.0

You can create an annotated tag like this git tag -a v1.0.0 -m "First release" or lightweight tag git tag v1.0.0 without descriptions. To push on server git push origin --tags. To delete git tag -d v1.0.0 or delete on server git push origin --delete v1.0.0. You can switch to tag by git checkout v1.0.0, if you make changes and commit them in tag’s “detached HEAD” state, your new commit won’t belong to any branch and will be unreachable. Then you need to create a new branch git switch -c branch-name v1.0.0 which will contain your commit.

You can generate a build number with this command git describe main if you have annotated tags; if you use lightweight tags, you should add --tags flag.

Archives

Git allows you to create archives for your releases:

git archive main | gzip > `git describe main`.tar.gz

git archive main --format=zip > `git describe main`.zip

Submodules

You can add a submodule by this command git submodule add <url>. To update a submodule, you must execute this git submodule update --remote <submodule_name>. To clone a project with submodules git clone --recurse-submodules <url> or in an already cloned repo run this git submodule update --init --recursive.

History rewriting

Change the base commit to solve merge problems when pulling git pull --rebase

When you fetch a feature branch from remote repo with few commits, you can merge it from a specific commit, skipping all commits above git cherry-pick abcd123

Interactive mode git rebase -i is a powerful tool to rewrite your Git history; for example, squash several commits in one, split one commit to several, change the commit order, or delete some commits. You can check out Drew DeVault’s guide or read chapter “Rewriting History” in the book “Pro Git”.

Debugging

Git provides two commands for debugging your project: git blame and git bisect.

The first command shows you line by line who last changed each line of a file git blame -L 70,80 Makefile. If you are refactoring a file into multiple files, you can see where sections of the code originally came from by passing the -C option.

And the second one carries out binary search in interactive mode. When you start it by git bisect start you should enter git bisect good if the current commit is good or git bisect bad if not. If you answered positively, it means that all commits below are also good and do not contain bugs, and Git will switch to the middle commit between the good commit and the last commit for effective search. The search continues until you find the bug, then run git bisect reset to reset HEAD to where you were before you started. You can fully automate this process by passing a script that runs tests and returns 0 in case of success or 1 in error.

$ git bisect start HEAD v1.0.0
$ git bisect run test-error.sh

Configuration

If you use HTTP authentication, you can save your credentials in order to avoid entering a password git config --global credential.helper cache

Aliases

Aliases is useful shortcuts, like in .bashrc, here’s an instance of a handy ones:

1git config --global alias.co checkout
2git config --global alias.br branch
3git config --global alias.ci commit
4git config --global alias.st status

GUI

Git has graphical tools based on the tk library; git gui for managment and gitk for browsing repository.

Contributing

Git is decentralized VCS (Version Control System) by default, like Email, and there are a few methods for co-development:

  1. Sending patches via Email
  2. Main developer, clone and merge the feature branch from your own git repository
  3. Sending a git bundle as you wish

As a general rule, your commit messages should start with a single line that’s no more than about 50 characters and that describes the changeset concisely, followed by a blank line, followed by a more detailed explanation. The Git project requires that the more detailed explanation include your motivation for the change and contrast its implementation with previous behavior β€” this is a good guideline to follow. Write your commit message in the imperative: “Fix bug” and not “Fixed bug” or “Fixes bug.” Here is a template you can follow, which we’ve lightly adapted from one originally written by Tim Pope.

Patches via Email

Email setup guide for Git.

Get patch: git show -p HEAD > patch.diff

Get pretty patch for contributing: git format-patch -M origin/main

Apply patch: git apply patch.diff

Apply pretty patch: git am 0001-your-patch-name.patch

Remote repository

In this case, you clone the project, create a feature branch in which you’re creating your feature, and then you push this feature branch to your own git repository. You inform the main developer about your feature branch, and he should add it to remotes or just pull your branch. If everything is okay, he can merge it into the main branch.

Git bundle

In this case, you create a single binary file of the repository with all your changes, for example, in the feature branch, and send this file via email or as you wish.

Suppose, your repository looks like this:

$ git log --oneline
71b84da Last commit - second repo
c99cf5b Fourth commit - second repo
7011d3d Third commit - second repo
9a466c5 Second commit
b1ec324 First commit

and you want to send only your last three commits, then you need to define a range of commits in this command: git bundle create <filename>.bundle main ^9a466c5

You can send this file to the developer. For first, he has to verify your bundle git bundle verify <filename>.bundle and after this it can be applied git pull <filename>.bundle

Plumbing and Porcelain

Show commit count git rev-list HEAD --count

Paradigms

Lately, developers have been returning to Trunk Based Development. It acts as an antagonist against branch hell. The emphasis here is on CI, which runs tests and ensures that the code being contributed is error-free, so developers with a high development culture can afford to send commits directly to the main branch. Larger projects, use short-term feature branches, in which developers work throughout the day and at the end of which they merge their changes. However, some old projects such as a Git still using a four-branch model: main, next for merging stable feature branches, seen for merging raw feature branches, and maint for maintenance backport.

Git on server

Usually used Nginx and Fcgiwrap for http connections and cgit as a frontend. In the case of ssh you almost don’t need to set up anything, just the home directory of Git user with repositories. To handle git:// connections used git-daemon git daemon --reuseaddr --base-path=/srv/git/ --export-all --enable=receive-pack --informative-errors --verbose /srv/git/.

Here are useful links if you decide to raise your own git server:

Hooks

It’s a standard way to organize CI/CD by handwriting scripts, which live in the .git/hooks directory. There are client-side and server-side hooks. Sadly, but the hooks are not cloned, so you need to hold it in a separate place or repo. Server side hooks are located in the bare repository on the server and can function to build and deploy your Hugo website every time you pull your changes, for example.

Summary

It’s just a quick overview that includes only general functionality, and I strongly recommend you to read the book Git Pro.

#tech #guide #git

Reply to this post by email β†ͺ