Concepts

Index

The index is a binary file (generally kept in .git/index).

Serves as a staging area to write out the next tree object to be committed.

Your working tree --- index --- committed.

Commit

Commits are not changes. A commit is a snapshot of your entire project — all the files, in their current state.

Tag

Annotate tag

An annotated tag has a message that can be displayed with git-show(1), while a tag without annotations is just a named pointer to a commit.

git tag <tagname>
git tag -a <tagname> -m '<message>'

git - What is the difference between an annotated and unannotated tag? - Stack Overflow

Scripts

Git describe

The command finds the most recent tag that is reachable from a commit. If the tag points to the commit, then only the tag is shown. Otherwise, it suffixes the tag name with the number of additional commits on top of the tagged object and the abbreviated object name of the most recent commit.

So when you execute git describe, and it shows v7.2.0-2908-gb1a7753bd5, which means the most recent tag is v7.2.0, and it is 2908 commits far from HEAD, and the HEAD is b1a7753bd5. The "g" prefix stands for "git" and is used to allow describing the version of a software depending on the SCM the software is managed with. This is useful in an environment where people may use different SCMs.

By default (without --all or --tags) git describe only shows annotated tags.

Why is it that the "git describe" command sometimes produces different results on different machines even though they are working with the same git repository?

Such as one 1 machine it is v7.2.0-2908-gb1a7753bd5, but on the other machine, it becomes v6.1.0-13182-gb1a7753bd5.

Because the remote is different, so the tags are different and it produce different output.

Q&A

Why git merge-base is for determining two commits, not for two files?

How to delete remote tags in a batch?

git push --delete origin (git tag -l | grep -i bkc)

Diff and merge

diff is 2-way merge.

Merge logic

git merge algorithm:

  1. find the merge base;
  2. calculate two diffs: from the merge base to the first branch, and from the merge base to the second branch.
  3. to form the merge commit, Git applies both diffs to the merge base.

because a diff/patch contains the line number it should apply to, so if two diff change the same line, a conflict will occur.

How does git apply work?

If a patch does not apply at the exact line number stored in the diff file, patch tries to find the right line a couple of lines adjacent to the original one based on the context.

git - How do diff/patch work and how safe are they? - Stack Overflow

Diff and patch

Git 提供了两种补丁方案,一种是通过 git diff 生成的 .diff 文件,第二种是通过 git format-patch 生成的 .patch 文件。

通过 git diff 生成的文件不含有 commit 信息,可以指定文件生成 diff,也可以指定单个 commit,多个 commit 生成 。通过 git format-patch 生成的 .patch 文件 含有 commit 信息。一个 commit 对应一个 patch 文件。

git 补丁 - diff 和 patch 使用详解 - 腾讯云开发者社区-腾讯云

In summary, git format-patch is useful to transmit a commit, while git diff is useful to get a diff between two trees.

What is the difference between 'git format-patch and 'git diff'? - Stack Overflow

What's the difference between 'commit' and 'revision'?

So "revision" refers to the id you can use as a parameter to reference an object in git (usually a commit).

A "commit" in Git generally designates a "commit object"

So:

  • a commit designates one of the git objects (others are blobs, tree, tags, notes),
  • a revision is a way to reference a git object.

version control - In git, what is the difference between a commit and a revision - Stack Overflow

Common ancestor and merge base?

A common ancestor that does not have any better common ancestor is a best common ancestor, i.e. a merge base.

How to know if a commit is in current repo

git cat-file -t $sha

How to unstage current working dir?

git reset

Git clone 断点续传

mkdir <your-repo>
git init
git fetch <项目地址>
git checkout FETCH_HEAD
git remote add origin <<项目地址>
git pull origin master
git checkout master

Git force pull to override local

git fetch --all
git reset --hard origin/master

Merge conflict

A merge conflict happens when two branches both modify the same region of a file and are subsequently merged. Git can't know which of the changes to keep, and thus needs human intervention to resolve the conflict.

Move branch pointer to different commit

git branch --force <branch-name> [<new-tip-commit>]

If new-tip-commit is omitted, it defaults to the current commit.

new-tip-commit can be a branch name (e.g., master, origin/master).

You can make master point at 1258f0d0aae this way:

git checkout master
git reset --hard 1258f0d0aae

But you have to be careful about doing this. It may well rewrite the history of that branch. That would create problems if you have published it and other people are working on the branch.

git - How do I make a branch point at a specific commit? - Stack Overflow

Git checkout remote branch

git switch -c <branch> <remote>/<branch>

Delete branch

delete local branch:

git branch -d <branch>

delete remote branch:

git push <remote> --delete <branch>

Difference between git switch and git checkout

Well, according to the documentation you link to, its sole purpose is to split and clarify the two different uses of git checkout:

  • git switch can now be used to change branches, as git checkout <branchname> does
  • git restore can be used to reset files to certain revisions, as git checkout -- <path_to_file> does

People are confused by these different ways to use git checkout, as you can see from the many questions regarding git checkout here on Stackoverflow. Git developers seem to have taken this into account.

What's the difference between git switch and git checkout branch - Stack Overflow

Cherry-Pick to working copy without commit

Use '-n' flag with the cherry-picking which is "no commit".

git cherry-pick -n <HASH>

Git: Cherry-Pick to working copy without commit - Stack Overflow

How to modify existing, unpushed commit messages?

If the commit you want to fix isn’t the most recent one:

  1. git rebase --interactive $parent_of_flawed_commit

    If you want to fix several flawed commits, pass the parent of the oldest one of them.

  2. An editor will come up, with a list of all commits since the one you gave.
    1. Change pick to reword (or on old versions of Git, to edit) in front of any commits you want to fix.
    2. Once you save, Git will replay the listed commits.
  3. For each commit you want to reword, Git will drop you back into your editor. For each commit you want to edit, Git drops you into the shell. If you’re in the shell:
    1. Change the commit in any way you like.
    2. git commit --amend
    3. git rebase --continue

Modify a specific commit

git - How to modify a specified commit? - Stack Overflow

Git index, working tree and head

git - How to modify existing, unpushed commit messages? - Stack Overflow

Change git commit author name

git commit --amend --author="Lei Wang lei4.wang@intel.com"

Cherry-pick avoiding staging

An alternative would be to use apply instead of cherry-pick:

git show <commit> | git apply

This will apply the changes made in <commit> but will not add them to staging or create a commit.

Git merge/cherry-pick avoiding staging - Stack Overflow

Create a new branch from a previous commit using Git

If I have n commits, how can I branch from the n-3 commit?

git branch branchname <sha1-of-commit>

Branch from a previous commit using Git - Stack Overflow

Rename a branch

git branch -m <old> <new>

Git discard staged changes

git reset --hard

git revert Vs git reset

If a commit has been made somewhere in the project's history, and you later decide that the commit is wrong and should not have been done, then git revert is the tool for the job. It will undo the changes introduced by the bad commit, recording the "undo" in the history.[^1]

If you have made a commit, but haven't shared it with anyone else and you decide you don't want it, then you can use git reset to rewrite the history so that it looks as though you never made that commit.[^2]

Git revert should be used to undo changes on a public branch, and git reset should be reserved for undoing changes on a private branch.[^3]

Git checkout

It should be noted that git checkout will not remove added files since then. please refer to:

Ref: