Skip to content
Fu Zuoyou edited this page Nov 15, 2013 · 1 revision

Git note

2013-9-30, yoyo~ from: http://git-scm.com/book/zh

I. install

  1. git-config + (--system | --global | current_div)
    • user.name
    • user.email
  2. windows: ~/.gitconfig, or .git/config

II. basic usage

  1. initial new repo
    • git init to make dir init for git
    • git add *.c add files into git
    • git commit -m 'some words'
  2. clone repo
    • git clone url (SSH, https)
  3. File Status
    • git status check status
      • untracked files excludes (didn't git add)
      • unmodified unmodify after git add, or after git commit
      • modified
      • staged git add add modified file into staged
      • file may appear twice in status, mind that it's different snapshot(version) of the file
    • cat .gitignore
      • # or emptyline will be ignored by git
      • glob match (shell re: *, [ab-c], ?)
      • to ignore dir, add / after re
      • to avoid some file, add ! before re
    • git diff
      • git diff only display diff that are not staged
      • git diff --cached diff between staged and last commit
  4. git commit
    • notice : you may forget git add unless you call git commit -a to stage all
  5. move file
    • git rm delete file(both disk and git!!)
    • git will auto check your file, so if you del some file yourself you should use git rm to mark your file.
    • If you have the file staged, you should use git rm -f force to rm
    • git rm --cached file|glob match will not rm your file on disk (you could use git rm \*.log, to recurse del '*.log' file in all dir)
    • git mv equal to mv a b, git rm a, git add b
  6. look up history
    • git log ex: git log -p -2, -p display detail every submit, -2 latest 2 submit(there is many other para to use like --stat, --pretty=(online|short|full|fuller|format:"%h %ar ..."),--graph)
  7. cancel
    • git commit --amend to commit again
    • git reset HEAD <file>... to cancel commit some file
    • checkout, reset not recommand to use because it take last staged file and discard all changes
  8. remote repo
    • git remote to show every remote repo (default name : origin), -v for bervose
    • git remote add [shortname] [url] then you can fetch it
    • git fetch [remote-name:pb] fetch to local, but won't automatically merge your work branch
    • git pull [remote-name] [branch-name] (ex. git push origin master) it will only work when you have access to branch, or nobody changed branch, or you have to fetch their work to the branch and add into your own work then you can push your work with the latest branch.
    • git remote show [remote-name] tell you some useful infomation
    • git remote rename [old] [new], git remote rm [name]
  9. tagging
    • git tag to list all tag, git tag -l 'v1.4.*'
    • there are 2 type of tag:
      • lightweight ex. git tag [tag-name]
      • annotated ex. git tag -a v1.4 -m 'msg'
    • git tag -s(ign) ..., git tag -v(erify) to sign and check tag
    • git tag -a v1.2 [CRC or some head chars of CRC] to add additional tag
    • git push won't push tag onto remotes, you have to git push origin [tagname]. to push all tags: git push origin --tags

III. advance

  1. every git commit will 计算每一个子目录的校验和,然后在git仓库中保存一个commit(info) -> tree(dir) -tree-> blob(file) 的树形结构
  2. 每次的修改对象(commit)将会包含上一次提交对象的指针
  3. git branch [branch-name] 将会在当前commit对象上新建一个分支指针, Git中的分支仍然是一个指向commit对象的指针
  4. Git保存有一个HEAD的特殊指针, 指向当前工作中的本地分支的指针, 使用命令git branch仅仅是创立分支而并未将工作目录切换
  5. git checkout [branch-name] 将工作目录(HEAD)切换过去
  1. git checkout -b iss53 新建分支iss53并切换过去
  2. 在切换分支时注意暂存区与工作目录中未提交的修改,可能会与即将checkout的分支产生冲突,所以可以先提交所有修改(在切换分支时,git将会恢复工作目录的内容至原分支)
  3. 做比如修补bug时,在master新建一个hotfix分支,测试之后git checkout master, git merge hotfix, 由于是单线分支不会有分歧,此时git将master指针简单右移,称为快进(Fast forward), 然后删掉hotfix分支(指针) git branch -d hotfix
  4. 想把iss53与master合并了,git checkout master, git merge iss53, 由于当前更新的master指向对象C4并不是iss53(C5)的直接祖先,因此git将会计算C4,C5以及他们共同祖先C2,进行一次三方合并,创建一个祖先为C4,C5的对象C6。接下来删除没有用的iss53:git branch -d iss53
  5. 如果不同分支中同一个部分被修改,那么就无法简单合并,git merge iss53时将会报CONFLICT的错误, 使用 git status查阅,任何包含未解决冲突的文件将会以unmerged标出. git将会在其中加入标准的冲突解决标记,
    <<<<<<< HEAD:index.html
    <div id="footer">contact :[email protected]</div>
    =======
    <div id="footer"> please contact us at [email protected]
    >>>>>>> iss53:index.html
    自行整合他们,删除标记。git add 将它们保存到暂存区域,表示冲突解决。git mergetool GUI, git status 检查状态,最后git commit提交
  1. git branch list all branches, * 表示当前分支, -v 检视各分支最后commit
  2. git branch --merge 查看已经合并的分支, 可以删除之, --no-merged 尚未合并的分支, 删除则用 git branch -D [name]
  1. 长期分支
  2. 特性分支
  1. (远程仓库)/(分支名) ex:origin/master, clone时git将会把远程分支命名为origin, 并建立一个master分支, 本地命名为origin/master(不可修改), 同时又镜像建立一个本地master分支, 工作即从这里开始.
  2. 如果你对本地分支做了改动, 其他人推送了更新, 那么双方的分支都会前进, (由于暂且没有通讯, 本地用来记录远程分支的指针如origin/master不会发生移动,但本地分支master已经移动)
  3. 可以用 git fetch origin 同步远程服务器到本地, 同时origin/master被修改
  4. 例子: 假设有一个快速开发分支team, git add team [url], git fetch team, 于是就有了远程分支 team/master, 远程分支也可以指向本地内容
  5. 推送本地分支 git push [远程仓库] ([本地分支]:)[远程分支名]
  6. 将远程分支合并到本地 git merge origin/name
  7. 新建分支 git checkout -b [本地] origin/name, 本地与远程push pull动作自动挂钩, 称为跟踪分支,
  8. 删除分支 git push [远程名] :[远程分支], 即用空分支替代远程分支
  1. mergerebase, ex: git checkout test, git rebase master, rebase 将把在一个分支里提交的改变在另外一个分支里重放一边, 原理是回到两个分支的共同祖先, 根据当前分支后续的历次提交对象, 以基底分支最后提交为出发点, 逐个应用提交改变, 使当前分支改写为master的直接下游. 再用一次快进合并, 使master指针移动至当前.

现在的 C3' 对应的快照,其实和普通的三方合并,即上个例子中的 C5 对应的快照内容一模一样了。虽然最后整合得到的结果没有任何区别,但衍合能产生一个更为整洁的提交历史。如果视察一个衍合过的分支的历史记录,看起来会更清楚:仿佛所有修改都是在一根线上先后进行的,尽管实际上它们原本是同时并行发生的。
一般我们使用衍合的目的,是想要得到一个能在远程分支上干净应用的补丁 — 比如某些项目你不是维护者,但想帮点忙的话,最好用衍合:先在自己的一个分支里进行开发,当准备向主项目提交补丁的时候,根据最新的 origin/master 进行一次衍合操作然后再提交,这样维护者就不需要做任何整合工作(译注:实际上是把解决分支补丁同最新主干代码之间冲突的责任,化转为由提交补丁的人来解决。),只需根据你提供的仓库地址作一次快进合并,或者直接采纳你提交的补丁。
请注意,合并结果中最后一次提交所指向的快照,无论是通过衍合,还是三方合并,都会得到相同的快照内容,只不过提交历史不同罢了。衍合是按照每行的修改次序重演一遍修改,而合并是把最终结果合在一起。

  1. 总之慎用衍合就是了~