Git笔记
05 Jan 2012一图胜千言
获取
git clone git@github.com:liuzhongshu/liuzhongshu.github.com.git
如果网速慢,可以加代理 -c http.proxy="http://127.0.0.1:1080"
, 这个是针对http协议,如果clone的是git url
初始化远程仓库
这是很常见的操作,比如在github上已经创建了一个仓库,要将本地的目录上传上去,如果本地目录还不是库,先做以下操作
cd <localdir>
git init
编辑好.gitignore文件
git add .
git commit -m 'message'
然后将远端地址加上并同步,origin只是一个标签,可以任意取,-u会把这个信息记住,下次只需要git push就可以了。
git remote add origin <url>
git push -u origin master
url通常有两种,一种是https格式,一种是ssh格式,ssh格式需要事先在服务器端配置好ssh key,好处是以后都不需要输入账号密码了。
日常操作
可以参考几种工作模式,比如gitflow, github flow, gitlab flow,通常个人开发者使用github flow就可以了,复杂情况下需要使用gitlab flow,但总的来说基础是下面几个命令:
#创建一个分支:
git checkout -b fix-xx master
#修改结束后,合并到master分支:
git checkout master
git merge --no-ff fix-xx
git tag -a xx
# 需要的话删除分支,如果分支没有合并,可以用-D强制删除
git branch -d fixbug-xx
上面的-no-ff的作用,可以用下面一张图说明:
更多分支操作
#查看远端分支
git branch -r
本地操作
- 添加所有修改,包括删除的文件
git add . -A
- 查看修改情况
git status
- 提交到本地
git commit -m "comment"
- 取消,下面两条都可以,暂存区域会取消,–hard会将修改的文件恢复到上次commit状态。
git reset
git reset --hard
- 比较,下面三条依次用最新版本,上次版本,上上次版本和本地进行比较
git diff
git diff HEAD~
git diff HEAD~2
更高级一点的用法,调用外部工具比较一个特定版本(用hash)的修改:
git difftool c1ac~ c1ac
#比较两个分支
git difftool branch1..branch2
可以加-d表示目录比较,更方便(而且可以把beyond compare设置为difftool)。
撤销
和svn不一样,git里本地的commit,如果没有push,是可以撤销的,方法很简单,比如撤销最后一次修改
git reset --soft HEAD~
git commit -m 'comment'
reset有三种模式 –soft,–mixed, –hard 其中–mixed是缺省模式,三者差异在于
- –soft 不丢失本地修改,撤销的东西都合并在暂存区域,用来合并几次commit到一个commit最合适。
- –hard 比较危险,本地没有提交的修改和撤销的修改全部丢弃。
- –mixed 所有撤销的内容和本地修改合并到workcopy。
历史
git log可以很容易看其他分支的历史,只需要加上分支名称,比如git log feature1
,如果只想看这个分支上的修改,不包括更早的历史,可以后面用..的方式,比如feature1是从master拉出来的,可以用
git log master..feature1
release notes
通过git log自动形成release notes是个不错的主意
git log -5 --pretty=format:"%s"
GUI工具
- 很多人低估了内置的gui,使用git gui可以方便调出,在查看log和diff时,还是比较方便的,如果大部分文件是utf-8编码,可以设置下面这个全局设置,防止diff时乱码
git config --global gui.encoding utf-8
- smartgit 也还不错
diff和merge工具
git可以配置调用外部diff工具,通常我习惯用beyond compare,可以在~/.gitconfig下增加以下配置
[diff]
tool = bc3
[difftool]
prompt = false
[difftool "bc3"]
cmd = \"c:/program files (x86)/beyond compare 3/BCompare.exe\" \"$LOCAL\" \"$REMOTE\"
[merge]
tool = bc3
[mergetool]
prompt = false
keepBackup = false
[mergetool "bc3"]
cmd = \"c:/program files (x86)/beyond compare 3/BCompare.exe\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"
trustExitCode = truecss
密码
在使用github时每次都输入密码是很麻烦的事,两个方法:
- 可以设置
git config credential.helper store
之后就可以缓存账号密码了。 - 如果服务器端支持ssh协议,可以把远端地址迁移到ssh协议上,这样:
git remote set-url origin git@xxx.git
或者clone的时候就使用ssh地址(非https地址)
换行处理
git缺省会自动做换行处理,我发现在某些情况下会导致问题,比如使用vue init一个github库时,bat文件没有正确转换回dos格式,所以我一般:
git config --global core.autocrlf false
log里的中文乱码
不记得从哪个版本的git开始,windows下看git log中文总是乱码,需要设置一个环境变量
LESSCHARSET=utf-8
hook
我最常用的一个hook,是自动push(会丢失git reset这个后悔药),在.git\hooks下放一个post-commit文件,内容为:
#!/bin/sh
git push origin master
可惜的是这个hook文件没有入库,导致每次clone后这个hook文件都要手工重建,替代方案是git有个全局配置,设置
git config --global init.templatedir "~/.git_template"
然后在~/.git_template/hooks下面放上脚本就可以让以后的新库也有这个文件,但还是解决不了新clone的问题,git2.9以后版本引入新的配置
git config --global core.hooksPath /path/to/my/centralized/hooks
勉强算是部分解决了这个问题(但很不灵活),挺遗憾,为什么hook不入库呢~
git库为什么这么大
可以用下面的命令找到历史上的大文件
git rev-list --all --objects | \
sed -n $(git rev-list --objects --all | \
cut -f1 -d' ' | \
git cat-file --batch-check | \
grep blob | \
sort -n -k 3 | \
tail -n40 | \
while read hash type size; do
echo -n "-e s/$hash/$size/p ";
done) | \
sort -n -k1
删除历史文件
要从库中删除历史上的大文件,可以用bfg.jar,很容易
git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push