Git学习笔记

Git

Git是一个免费并且开源的分布式版本控制系统,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。如今,Git已成为最受开发者欢迎的版本控制系统。

自从用了Git,修改文件再也不用命名成file1,file2,file2改进版,file最终版…

注意: 所有的版本控制系统,只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等。而图片、视频这些二进制文件,没法跟踪文件的变化,也就是只知道图片从100KB改成了120KB。Git跟踪并管理的是修改,而非文件。

Notes

1.创建版本库

创建一个空目录,然后通过git init命令把这个目录变成Git可以管理的仓库:

$ mkdir learngit
$ cd learngit
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

2.添加和提交

把一个文件放到Git仓库只需要两步:

工作区有一个隐藏目录.git,是Git的版本库,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

git add之前若需撤销修改,用git checkout -- <file>...命令。

git add实际上就是把文件修改添加到暂存区,逆操作是unstage: git reset HEAD <file>...

git add

git commit实际上就是把暂存区的所有内容提交到当前分支,逆操作是git reset --hard HEAD^

git commit

3.版本回退

使用git log命令时,一大串类似3628164...882e1e0的是commit id(版本号)

$ git log
commit 3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao <askxuefeng@gmail.com>
Date:   Tue Aug 20 15:11:49 2013 +0800

append GPL

在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100,也可指定commit id

$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed

$ git reset --hard 3628164
HEAD is now at 3628164 append GPL

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是改变HEAD指针的指向。

4.远程库(Github)

由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,在使用Github之前,需先进行以下设置:

  1. 创建SSH Key:$ ssh-keygen -t rsa -C "youremail@example.com"
  2. 用户主目录下里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,登陆GitHub,打开“SSH Keys”页面:在Key文本框里粘贴id_rsa.pub文件的内容。

添加远程库

如果本地库有内容,而远程库没有内容,则在Github上“Create a new repo”,然后将本地仓库与之关联,这样就可以把本地仓库的内容推送到GitHub仓库了。

$ git remote add origin git@github.com:michaelliao/learngit.git

$ git push -u origin master

从远程库克隆

如果远程库有内容,而本地库没有内容,则直接从远程库克隆。

$ git clone git@github.com:michaelliao/gitskills.git

从远程库pull

如果远程库与本地库都有内容,并且存在冲突,则本地库无法向远程库push,解决办法很简单,先用git pull把最新的提交从origin/master抓下来,然后,在本地合并,解决冲突,再推送。

$ git pull

fix conflicts...

$ git push origin master

5.分支管理

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。创建版本库时自动创建master主分支。创建新的分支dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上。当dev上的工作完成了,直接把master指向dev的当前提交,就可以把dev合并到master上。

master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:

git commit

Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作。

# 保存工作现场
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge

# 查看工作现场列表
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge

# 恢复工作现场方法1
$ git stash pop

# 恢复工作现场方法2
$ git stash apply stash@{0}
...
$ git stash drop

6.自定义Git

忽略特殊文件

在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。

# MacOS X:
.DS_Store

# Python:
*.py[cod]
*.so

# My Config:
*.txt

配置别名

例如,用git st表示git status命令,git br表示git branch命令…:

$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.cm commit
$ git config --global alias.br branch
$ git config --global alias.unstage 'reset HEAD'
$ git config --global alias.last 'log -1'
$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
...

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。每个仓库的Git配置文件都放在.git/config文件中。而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中:

$ cat .gitconfig
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status
[user]
    name = Your Name
    email = your@email.com

配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。

本文整理自Git教程-廖雪峰的官方网站 & Git官方网站