常用回退操作

首先给出一些常用回退操作参考:

git checkout . 回退没有add到暂存区的更改

git reset --hard 回退所有add到和没有add到暂存区的更改。后面如果跟上commit或者分支名,也可以直接变更已经commit的更改,原理是将分支名或HEAD指针重新指向。

git clean -df 删除没有add的其他文件和目录。如果已经add而没有commit,用git reset --hard的时候就会删除。

git notes

手撸git实录

git object

three attributes:

  • type
  • size
  • content

and has a hash name, computed with these 3 attributes

git directive analysis

git init

create this directory structure in one empty directory. 这是满足git初始化条件最低的目录结构

.
└─.git
    │  config
    │  description
    │  HEAD
    │
    ├─hooks
    ├─info
    │      exclude
    │
    ├─objects
    │  ├─info
    │  └─pack
    └─refs
        ├─heads
        └─tags

git add test.txt

  1. create binary compress file for a.txt(git object).

    can be done by git hash-object -w test.txt. even the file is empty, the meta info of the file will be compressed and stored in git object.

    a hash string is printed on the screen, just like 3b18e512dba79e4c8300dd08aeb37f8e728b8dad. you can use git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad command to see the files’ content

  2. add a.txt into index.

    can be done by git update-index --add --cacheinfo 100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt. if the file is already in index and just updated to a new version, it is ok to run just git update-index test.txt.

    than .git/index will be updated. use git ls-files --stage to look its content.

git commit

  1. create tree object

    git write-tree

    store a tree object and show the hash SHA-1. actually save index’s content.

  2. create commit object accroding tree object and parent commit object(*)

    echo 'commit message' | git commit-tree <tree-hash> -p <last-commit-hash -p <last-commit-hash> if there are two parent commit means this is a merge commit

    a commit object will be stored and show the hash SHA-1.

commit contains info just like:

tree bcf9e352e75e1997deafc956292b33ee7c207553
parent 498eca8a43098c77c6b7c164cdf9d5b8aeb76f54
author claws <jingjiecb@gmail.com> 1637236383 +0800
committer claws <jingjiecb@gmail.com> 1637236383 +0800

add a.txt from master                                                                                                                   

if it is the initial commit, there will be no parent. else if it is a merge commit, there will be two parents

git log

  1. read .git/HEAD and get the branch pointer’s name(branchName)
  2. read .git/refs/heads/branchName to get the commit(snapshoot) hash
  3. git cat-file -p hash and get the massage of this commit, and the parent(‘s) commit hash(if has)
  4. repete 3 until initial commit

git checkout

checkout files: set the file with the content in git object. usually use git checkout -- filePath to abondon the modifying in work tree.

checkout tag head commit: set the HEAD pointer to it, then set index the tree in the commit object, then set all files same with the object in the tree.

you can use git checkout --ours test.txt to select our version while merging, or use git checkout --theirs test.txt to select their version.

use git --work-tree=path/to/other/directory checkout -- . to checkout all files in git repository to other directory instead of current work directory.

warning: may generate detached head problem. modify the .git/HEAD file directly can solve the problem

git reset

reset the current branch’s pointer to some commit. has 3 mode: –mixed(default), –hard, –soft

  • –mixed(Default) will not change current work tree files. but will change index same with the tree in that commit.
  • –soft will only change the current branch pointer to one commit. without change the workspace and index(stage)
  • –hard will change the branch pointer, index and the workspace. workspace will be changed thoroughly(all file in index will be reset, new file will be deleted. but files not in index will not be influenced)

git merge

there are 3 situations when merge:

  • fast forward. no further commit on this branch, so just move the branch pointer to the coming branch’s latest commit.
  • auto-solve merge. no conflict happened, git apply both modifying, and generate a new commit whose parents are the current commit and the coming commit.
  • conflict merge. conflict happened, and must be desided manually. After all conflict solved, add and commit the change

the last two situations both generate a new merge commit.

git pull

by default, git fetch then git merge romote/master(e.g.)

git rebase

undo all modifying, checkout to the other commit(or branch or tag), the reapply the modifying there.

might cause rebase conflict.

use git pull --rebase to change pull stategy to rebase pull, first git fetch then git rebase remot/master(e.g.)