git随记 09 August 2012
写作思路
-
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对象种类: 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
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
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
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
git checkout . git checkout –
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文件
-
在.gitignore中添加文件,如果已经被管理了,那么闲使用git rm [-r] –cached [file/dir] 删除,然后就会生效。注意.gitignore可以用于版本管理,git是不会上传空文件夹的,此时可以使用空的.gitignore文件来上传。
-
在.git/info/exclude里面设置,这是本地的管理
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