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 add <file>...
: 将文件添加到仓库git commit -m "message"
: 将文件提交到仓库
工作区有一个隐藏目录.git,是Git的版本库,其中最重要的就是称为stage
(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
git add
之前若需撤销修改,用git checkout -- <file>...
命令。
git add
实际上就是把文件修改添加到暂存区,逆操作是unstage
: git reset HEAD <file>...
。
git commit
实际上就是把暂存区的所有内容提交到当前分支,逆操作是git reset --hard HEAD^
。
3.版本回退
git status
: 查看仓库当前的状态git diff
: 查看具体修改内容git log
: 查看版本变化的历史纪录git reset --hard HEAD^/commit id
: 回退到指定版本
使用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之前,需先进行以下设置:
- 创建SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
- 用户主目录下里找到
.ssh
目录,里面有id_rsa
和id_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
上。
git branch
: 查看分支git branch <name>
: 创建分支git checkout <name>
: 切换分支git checkout -b <name>
: 创建+切换分支git merge <name>
: 合并某分支到当前分支git branch -d <name>
: 删除分支git branch -D <name>
: 强行删除没有被合并过的分支
master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:
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官方网站。