程序人生 A log of my life

Git笔记

一图胜千言

获取

git clone git@github.com:liuzhongshu/liuzhongshu.github.com.git

初始化远程仓库

这是很常见的操作,比如在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
# 需要的话删除分支
git branch -d fixbug-xx

上面的-no-ff的作用,可以用下面一张图说明:

本地操作

  • 添加所有修改,包括删除的文件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

撤销

和svn不一样,git里本地的commit,如果没有push,是可以撤销的,方法很简单,比如撤销最后三次修改

git reset --soft HEAD~3
git commit -m 'comment'

Rebase

GUI工具

  • 很多人低估了内置的gui,使用git gui可以方便调出,在查看log和diff时,还是比较方便的,如果大部分文件是utf-8编码,可以设置下面这个全局设置,防止diff时乱码
git config --global gui.encoding utf-8

diff和merge工具

git可以配置调用外部diff工具,通常我习惯用beyond compare,可以在~/.gitconfig下增加以下配置

[diff]
    tool = bc3
[difftool]
    prompt = false
[difftool "bc3"]
    cmd = \"c:/program files (x86)/beyond compare 3/bcomp.exe\" \"$LOCAL\" \"$REMOTE\"
[merge]
    tool = bc3
[mergetool]
    prompt = false
    keepBackup = false
[mergetool "bc3"]
    cmd = \"c:/program files (x86)/beyond compare 3/bcomp.exe\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"
    trustExitCode = true

密码

在使用github时每次都输入密码是很麻烦的事,两个方法:

  • 可以设置git config credential.helper store之后就可以缓存账号密码了。
  • 如果服务器端支持ssh协议,可以把远端地址迁移到ssh协议上,这样:
git remote set-url origin git@xxx.git

hook

我最常用的一个hook,是自动push,在.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不入库呢~