Git Misc
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:
- find the merge base;
- calculate two diffs: from the merge base to the first branch, and from the merge base to the second branch.
- 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, asgit checkout <branchname>
does -
git restore
can be used to reset files to certain revisions, asgit 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:
-
git rebase --interactive $parent_of_flawed_commit
If you want to fix several flawed commits, pass the parent of the oldest one of them.
- An editor will come up, with a list of all commits since the one you gave.
- Change
pick
toreword
(or on old versions of Git, toedit
) in front of any commits you want to fix. - Once you save, Git will replay the listed commits.
- Change
- 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:
- Change the commit in any way you like.
git commit --amend
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:
- note: if you have added new files to your project since then, this won't delete them.
- Note that unlike this answer that says to use git checkout, git revert will actually remove any files that were added in any of the commits that you're reverting
Ref:
- :[^4]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. If you have modified a file in your working tree, but haven't committed the change, then you can use git checkout to checkout a fresh-from-repository copy of the file. 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.
- :[^5]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