Understanding Git Conceptually新手理解Git (Note)

来源:互联网 发布:剑三菊花dbm数据 编辑:程序博客网 时间:2024/06/07 02:03

https://www.sbf5.com/~cduan/technical/git/ 不错的教材,以下笔记是原创,概念部分翻译或改写了原文便于理解。


Repository & Commit Object & Head


Repository仓库: data structure in GIT, to manage [project/files]. 

= commit objects + heads(reference to commit objects)

store in ".git" sub-directory under root directory of the project.


Commit Object交付对象:

= files(reflecting the state of a project at a given point in time)  + reference to parent commit objects(usually one) + SHA1

Based on the above, you can visualize a repository as a directed acyclic graph of commit objects, with pointers to parent commits always pointing backwards in time, ultimately to the first commit. 


Head头:simply a reference to a commit object. Each head has a name.

[master head]; head => any heads. HEAD => selected as "current head".


*****practice*****

git init

git add ./test/*

modify one added file readme.txt

git commit

  *[ERROR] Aborting commit due to empty commit message

  **{RESOLUTION} type comments in commit file, not starting with # (vi save and quit => :wq)

  *[Question] Commit successful, but readme.txt was in status before modification. (verify from 'git diff' command) ???

  **[Answer]  If a file has not changed since the previous commit (the “parent” commit), Git will automatically include it in the commit you are about to perform. Thus, you only need to add files that you have newly created or modified. As a shortcut, git commit -a will automatically add all modified files (but not new ones). Note that if you modify a file but do not add it, then Git will include the previous version (before modifications) to the commit. The modified file will remain in place.

git commit -a  

(Then modified file is committed. 'git diff' shows empty message.)(*More precisely, git diff compares the staging area, that is, HEAD as modified by all added files, against the current state of all added files. Thus, if you add some but not all changed files and then run git diff, you will see only files that are changed but not added.)(git diff shows the diff between HEAD and the current project state. With the --cached option it compares added files against HEAD; otherwise it compares files not yet added.*)

(A) -- (B) -- (C)               |             master               |              HEAD

*****practice*****





Branch


Branch分支:Note on terminology: The terms “branch” and “head” are nearly synonymous in Git. Every branch is represented by one head, and every head represents one branch. Sometimes, “branch” will be used to refer to a head and the entire history of ancestor commits preceding that head, whereas “head” will be used to refer exclusively to a single commit object, the most recent commit in the branch.

CREATE git branch [new-head-name] [reference-to-(B)]

SWITCH git checkout [head-name]

Important note: if there are any uncommitted changes when you run git checkout, Git will behave very strangely. The strangeness is predictable and sometimes useful, but it is best to avoid it. All you need to do, of course, is commit all the new changes before checking out the new head.


*****practice*****

git branch test HEAD^

*[ERROR] More?

**{Unresolved} 看上去HEAD^读不出来,不能指向当前HEAD的父节点.。用git log里面上一个节点的SHA1前7位代替,成功创建分支,文件回退成功。???

Modify README.txt, adding new 'test branch' comment.

git commit -a

(current head is test, with committed new version)

         +-------------- (D)        /                 |(A) -- (B) -- (C)         |               |          |             master      test                          |                         HEAD
git diff test..master 显示C-master相对D的变化,(-)表示C和D比较少了什么,(+)表示C和D比较多了什么;信息量相当于以下两个命令总和再去掉共同项。

git diff test...master 显示C-master相对B(test和master的共同祖先)的变化

git diff master...test 显示D-test相对B(test和master的共同祖先)的变化

git log 显示目前branch的历史记录

git log test..master 显示C-master相对B(test和master的共同祖先)的变化记录

git log test...master 显示D-test相对B(test和master的共同祖先)的变化记录  。。。。没啥用处~~交换下上一个命令的test/master是一样效果

*****practice*****

So, in the example above, it may have been better to leave master at (B), where the paper was submitted to the reviewers. You could then start a new branch to store changes regarding new data. Ideally, in this pattern, the master branch is always in a releaseable state. Other branches will contain half-finished work, new features, and so on.

For developers, 如果是流水线操作,应该在同一个branch先后commit变化;如果是分属不同模块互不影响,应该分到不同branch,即使没完成也可以commit,不影响别人。猜和merge有关。





Merging


Merging合并:feature完成以后放进master让大家使用,或者从master抄最新版本避免merge时候冲突。

git merge [head]
git pull . [head]

         +---------- (D)        /             |(A) -- (B) -- (C) -------------- (E)        |             |           |      COMMON         MERGE      CURRENT                                  |                                 HEAD

假设运行git merge MERGE, 当前brach为CURRNET,执行效果为把MERGE合并到CURRENT里面,抄过来用。如果成功,HEAD当前节点(merge以后的新节点)会有MERGE和CURRENT两个父节点。运行命令的时候会做如下判断:

(1) 比较COMMON和MERGE,如果相同不操作 (需要抄的之前已经抄过了)

(2) 比较COMMON和CURRENT,如果相同fast forward merge,直接把CURRENT指向MERGE节点,不会产生新commit节点。

         +---------- (D)(E)        /             |(A) -- (B) -- (C)     |        |             |                 COMMON     MERGE,CURRENT                           |                         HEAD

(3) ELSE,试着把D相对B的改动放进E,如果没有冲突,就是下图的情况了。新节点会有D&E两个父节点,不影响MERGE本身。

         +---------- (D) ---------------+        /             |                  \(A) -- (B) -- (C) -------------- (E) -- (F)                      |           |      |                    MERGE   (previous) NEW=CURRENT+MERGE                             (CURRENT) |                                        HEAD
如果有冲突,不合并,提示用户修改冲突文件。To resolve the commit, edit the files to fix the conflicting changes. Then run git add to add the resolved files, and run git commit to commit the repaired merge. Git remembers that you were in the middle of a merge, so it sets the parents of the commit correctly.

(One disadvantage of doing the above is that your feature branch will end up with a lot of merge commits. An alternative that solves this problem is rebasing, although that comes with problems of its own.)

git branch -d will cause an error if the branch to be deleted is not reachable from another head.“dangling commit”




原创粉丝点击