写作思路

  • git历史简介

  • git原理简介

  • git使用场景举例

  • git命令随记

分个人篇和社区篇写

git概念: 工作区–workspace 暂存区 – stage/index 版本库 – repository 查看以上三者的文件树: 1.ll –fulltime 2.git ls-tree -l master => 查看tree object内容,非raw content 3.git ls-files -s=>暂存区的文件 git cat-file -s =>查看文件大小 或者 git write-tree git ls-tree -l repository object

git对象种类: commit tree blob

git的hash设计可以保证每一个版本的文件都有唯一的hash值,生成策略是commit/tree/blog+size+\000(null)+content,即使用文件大小和文件内容生成sha1sum,生成时机是添加到index上时。

git hash的sha1生成原理见《git权威指南》6.2 ##常用命令

git branch —- 列出所有分支,-r(remote branch) -a(local and remote branch) git branch feture1 — 新建一个分支feture1 git checkout feture1 — 切换到分支feture1 git status —- 查看目前分支下文件控制情况 git -d/-D feture1 — 删除分支feture1,d会检查feture1是否已经merge到其父分支,如果没有,不予删除。D直接删除 git log -1 –stat — 查看log信息,最近1条 git log –oneline git whatchanged — 显示文件变化情况 git add test — 添加test到index上 git add -u/-i => add files in index git add -a =>add all files with modified and new git reset --test ----作用与add相反,将test reset到某个commit版本,即自该版本之后的所有更改需要重新提交。不是信息回滚,保留当前文件内容,只是给予了再次提交文件的机会,可以借机修改提交信息,整理文档。 git commit test -m"add file test" --- 提交test文件到版本库 git commit -a -m"all changes" git commit --amend --- 合并到上一次的提交中

git merge feture1 — 合并并提交feture1的所有版本到当前分支,如果当前分支自建立feture1后无更改,则启动fastforward,可以添加参数–no-ff关闭该效果 git merge –squash feture1 —- 不合并feture1的所有版本到当前分支,而是将其文件变化合并,由用户决定再次提交一个版本,该命令可以保证主分支的整洁。 git commit -v —-可以查看diff内容

git ls-tree master

开启分支,合并的常用命令

git branch feture1

git checkout feture1

git add file git commit ..

git checkout master

git merge –squash –no-ff feture1

git commit -v

git branch -d feture1

取消某些错误提交

git reset file

git diff =>比较工作区和暂存区的差异 git diff master => 比较工作区和master的差异

git diff –cached =>比较暂存区和HEAD的差异

git diff –cached master => 比较暂存区和master分支比较

git commit -m”revert file”

撤销某一此commit造成的影响

git log –oneline git revert

回到某一次commit

git reset

使用git checkout file,即可将文件回复到以前的状态

git reflog

git reset HEAD@{1}

git reset –hard ---彻底回退到某一个版本,所有文件退回,不保存当前文件的内容此时只能通过上面的方式回去。

–soft 只回退commit信息,index文件仍然会保留,即直接commit就可以,不用add

–mixed 回退commit信息和index文件,源码保留,需要add了之后才能commit

分支合并上游分支的代码变化

git checkout feture1

git rebase master

这样master的代码修改就可以在feture1中使用了

临时保存代码

git stash

git stash apply

修改到一半的代码,又需要临时切换回去修改bug,此时派上用场

远程协作

git clone user@url:/path [local] #clone一个镜像

git branch -a #查看所有分支

git checkout branch_name #进入分支查看

git fetch origin master # fetch是把远程分支和提交信息等抓取下来,将FETCH_HEAD指向该分支 git merge origin/master #也可以改为FETCH_HEAD

后面三条可以改用pull git pull origin master #默认执行git merge FETCH_HEAD,存在fastforward的可能 但推荐用fetch,还有机会决定是否提交

在此时使用git reset HEAD^会回退两个commit,估计是因为merge的commit版本是自动生成的原因

git fetch orgin master:test 直接check到新分支test,否则是FETCH_HEAD

一般pull下orgin/master,然后在自己的分支上,rebase一下即可 git checkout branch git pull origin master git rebase master

merge后取消操作

git reset –hard

打tag

git tag =>显示所有的tag git tag v1 =>打一个轻标签v1,无附带信息 git tag -a v1 -m”version1” => 打一个附注标签,推荐方法 git tag -d v1 =>删除标签 git tag -a => 给某一个commit版本打标签

git checkout v1 => 切换到v1的tag,但是做的所有更改不会予以记录,必须git checkout -b newbranch才可以。

git push origin v1 => 将标签v1提交到git服务器 git push origin -tags => 将本地所有标签一次性提交到git服务器

重写提交说明

git commit –amend => 可以修改上一次的提交说明

git rm => remove a file from workspace and index git rm --cached => reomve a file from index/stage,change file to be untracked

git checkout . git checkout – =>使用stage的file来替换workspace的file git checkout . git checkout => 使用版本库的file来替换workspace的file和暂存区的file,意味着未提交的内容被丢弃

git commit -a => 应该避免使用,因为它丢掉了通过缓冲区对内容提交进行控制的能力

git stage上的更改,在切换分支后依然保留????

git ls-tree == git cat-file -p

git cat-file -t/-p=> repositroy object

git cat-file commit/blob/tree =>查看某个提交版本的情况

恢复删除的文件

删除了一个文件后,想要恢复,结合checkout和add命令即可恢复。 git checkout HEAD~1 – file git add -A

或者高阶用法

git cat-file -p HEAD~1:file > file 从blob对象中取出数据放入新建的文件中。

移动文件

git mv file file2

Git忽略语法

.gitignore文件编写,可以忽略自身。

.a #忽略.a的文件 !lib.a #不要忽略lib.a /TODO #忽略此目录下的TODO文件,子目录下的TODO文件不忽略 build/ #忽略所有build/目录下的文件 doc/.txt #忽略文件入doc/notes.txt,但是子目录下的txt不被忽略 .gitignore

打包发布

git本身提供栏打包命令,如下:

基于最新提交建立归档文件latest.zip git archive -o latest.zip HEAD

只将目录src doc建立到归档partial.tar中。 git archive -o partial.tar HEAD src doc

基于里程碑(tag)v1.0建立归档,并且为归档中的文件添加目录前缀1.0。 git archive –format=tar –prefix=1.0/ v1.0 |gzip > foo-1.0.tar.gz

GitHub使用的相关命令

  • create a new repository in github, such as helloworld. Then you will get an address “git@github.com:rockybean/helloworld.git”.
  • In your own workspace, use the following commands.

    mkdir helloworld; git init; touch README.md cat “haha” » README.md git add -A/-u git ss git la git ci -m”” git remote add origin “” git push [-u] origin master git ci –amend [–reset-author] [-C HEAD] git push -f => force push

    Branch管理:.git/refs/heads git checkout -b newbranch git push -u origin newbranch => 默认会在本地建立一个对应远程的分支,所以直接git push是可以提交的。

    git branch -d/-D newbranch

    git push origin :newbranch => 删除远程分支,该分支不能是默认分支

    Tag管理:.git/refs/tags 一共有三种创建方式: 轻量级创建:git tag [commit] => 创建的引用直接指向一个commit对象, 带说明的里程碑: git tag -a [] => 创建一个tag对象保存里程碑说明、里程碑的指向、创建里程碑的用户信息等,而tag引用指向该tag对象。 带签名的里程碑: git tag -s [] => 在上面的基础上引入PGP签名,保证tag的完整性和不可拒绝性。

      -m添加附注
    
      example:
          git tag -m "msg tag0" tag0 HEAD^
          git tag -m "msg tag0" -a tag0 HEAD^
          git tag mytag3
    
          git tag -l -n1
    
          git push origin refs/tags/*
    		
          git tag -d tag0
    
          git push origin :tag0 => delete tag from remote server
    

github pull request记录

clone一个源码

修改之后,创建一个pull-request即可

收到一个pull-request,一般不用网络提供的方法,在命令行自己完成更好

git remote add alfredway url git fetch url/alfredway

git merge alfredway/master

git pull alfredway master

git fetch origin master => store the fetched tip in FETCH_HEAD,not origin/master. to update origin/master,use fetch origin. git merge FETCH_HEAD

git fetch url => 抓取所有分支t

git rebase/merge都是合并命令

merge不是线性的,即一旦merge了一定会产生一个新的commit对象;而rebase可以线性提交,不产生新的commit信息

git rebase遇到冲突时,解决后,git rebase –continue即可,如果放弃了–abort,如果使用分支的信息,–skip –interactive可以交互式操作

git rebase branch=>当前分支为master,该命令相当于将master与branch共同祖宗节点开始的master修改文件的patch打到branch后面,提交是以master的commit进行的,最后master的指针指向的依然是其之前的commit变化,只不过commit对象的sha值不同了而已,当然打patch的过程中是会遇到冲突的。

git rebase适用与冲突不多,因为它可能要改好几次冲突(同一个文件被多次commit修改),不会产生额外的merge信息;merge适合冲突多,只要改一次就可以,会产生额外的merge信息。 “rebase”, as in “replay my work in my branch starting from a recent point from the branch B

rebase和merge结合使用: 你开发一个branch好了,想merge到master,并且push git co branch git rebase master git co master git merge branch => use fast forward merge git push 一般这样都是可以提交成功,否则就-f

远程分支,可以先check下来 git fetch url master:newbranch 之后进行同样的操作的,使得分支的变化在最上面

**push 本地分支a到远程分支b git push github a:b

**some command learned later

git remote -v

git show

git blame

git show 显示某次提交的信息

git show HEAD 显示master分支的版本信息 HEAD代表当前分支的头(也就是最近一次commit) 每一次commit都会有”parent commit”,可以使用^表示parent:

git show HEAD^ //查看HEAD的父母的信息 git show HEAD^^ //查看HEAD的父母的父母的信息 git show HEAD~4 //查看HEAD上溯4代的信息

要注意的是git-merge是会产生双父母的,这种情况这样处理: git show HEAD^1 //查看HEAD的第一个父母 git show HEAD^2 //查看HEAD的第二个父母

git merge-base commit1 commit2 确定commit1 和 commit2的父commit

git 实现文件read-only属性的方法

使用 git update-index –skip-worktree [file] 可以实现修改本地文件不会被提交,但又可以拉取最新更改的需求。适用于一些不经常变动,但是必须本地化设置的文件。

另外还有 git update-index –assume-unchanged [file] 该命令只是假设文件没有变动,使用reset时,会将文件修改回去。

参见链接

You need:

git update-index –really-refresh –no-assume-unchanged Makefile That will make any local modification to Makefile “invisible” to git, while keeping Makefile under source control.

链接说明了如何避免reset的时候把文件替换掉,方法是使用work-tree

update-index with the assume-unchanged is meant to be used to increase performance if your tree on your OS’s file system takes a long time to gather changes for a particular path. I would not recommend using it in your case unless you are ignoring those files due to lengthy git status or git diff or other command execution times.

assume-unchanged vs skip-worktree

git ignore文件

  1. 在.gitignore中添加文件,如果已经被管理了,那么闲使用git rm [-r] –cached [file/dir] 删除,然后就会生效。注意.gitignore可以用于版本管理,git是不会上传空文件夹的,此时可以使用空的.gitignore文件来上传。

  2. 在.git/info/exclude里面设置,这是本地的管理

github ignore

git大小写命名修改

git默认忽略大小写,即如果只是把文件名由大写改为小写,git会不记录该变化。配置core.ignorecase=false,既可以区别大小写,如果不想这样的话,可以执行如下命令:

mv Abc Abc.temp git add . mv Abc.temp abc git add . git ci

这样就可以提交大小写命名修改了。

如果遇到无法切换的远程分支,那么使用如下命令 git co -b web origin/web