一、简介
Git 是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。与Subversion、CVS、Perforce、Mercurial 等集中式版本控制系统相比,他们使用“增量文件系统” (Delta Storage systems), 就是说它们存储每次提交(commit)之间的差异。
Git正好与之相反,它会把你的每次提交的文件的全部内容(snapshot)都会记录下来。
二、安装git(略)
https://www.git-scm.com/download/
三、创建与操作本地git库
1、选择一个合适的盘符或者文件夹下,创建一个空目录
$ mkdir learngit
$ cd learngit
$ pwd
/c/Users/wangwenpeng/learngit
pwd命令用于显示当前目录。说明这个仓库位于C:\Users\wangwenpeng\learngit目录下
2、通过git init命令把这个目录变成Git可以管理的的仓库
$ git init
Initialized empty Git repository in /c/Users/wangwenpeng/learngit
3、添加文件到目录下(readme.txt),并把文件加入到暂存区
$ git add readme.txt
4、提交readme.txt到本地仓库git库
$ git commit -m"wrote a readme file"
5、修改readme.txt里面的内容,查看文件状态
$ git status
no changes added tocommit (use "git add" and/or "git commit -a")
git status命令可以让我们时刻掌握仓库当前的状态,上面的命令告诉我们,readme.txt被修改过了,但还没有准备提交的修改。
6、具体修改了哪些内容
$ git diff readme.txt
7、将修改过的readme.txt提交到本地库
$ git add readme.txt
$ git status
$ git commit -m"add distributed"
8、版本回退
$ git log
commit3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao
Date: Tue Aug 20 15:11:49 2013 +0800
append GPL
commitea34578d5496d7dd233c827ed32a8cd576c5ee85
Author: Michael Liao
Date: Tue Aug 20 14:53:12 2013 +0800
add distributed
commitcb926e7ea50ad11b8f9e909c05226233bf755030
Author: Michael Liao
Date: Mon Aug 19 17:51:55 2013+0800
wrote a readme file
git log
命令显示从最近到最远的提交日志
$ git log--pretty=oneline //格式化输出
3628164fb26d48395383f8f31179f24e0882e1e0append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030wrote a readme file
3628164fb26d48395383f8f31179f24e0882e1e0代表commit id
回退到上一个版本(向后回退)
$ git reset --hardHEAD^
HEAD is now at ea34578 add distributed
查看回退后的版本内容
$ cat readme.txt
Git is a distributed version controlsystem.
Git is free software.
根据commit id回退到指定的版本
$ git reset --hard3628164
HEAD is now at 3628164 append GPL
版本号没必要写全,前几位就可以了,Git会自动去找。
回退到下一个版本(向前回退)
$git reflog
ea34578 HEAD@{0}:reset: moving to HEAD^
3628164 HEAD@{1}:commit: append GPL
ea34578 HEAD@{2}:commit: add distributed
cb926e7 HEAD@{3}:commit (initial): wrote a readme file
$ git reset --hard3628164
HEAD is now at 3628164 append GPL
9、工作区和暂存区
工作区:当前项目版本库所在目录
暂存区(stage或叫Index):工作区有一个隐藏的 .git目录
10、撤销修改
场景1:
当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,
用命令git checkout --file
$ git checkout --readme.txt
git checkout-- readme.txt
意思就是,把readme.txt
文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
另一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
场景2:
当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
$ git reset HEAD^readme.txt
Unstaged changesafter reset:
M readme.txt
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
11、删除文件
从版本库中删除该文件,那就用命令gitrm删掉,并且git commit
$ git rm test.txt
rm 'test.txt'
$ git commit -m"remove test.txt"
[master d17efd8] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
误删工作区的文件,版本库里存在,进行恢复
$git checkout -- test.txt
四、远程仓库
1、 添加远程库
第一步,在gihub或者gitlab远程服务器中创建自己的远程仓库
第二步,通过gitremote命令进行本地库与远程库关联
$ git remote add origin [email protected]:michaelliao/learngit.git
第三步,把本地库的所有内容推送到远程库(默认推送到master分支)
$ git push -u origin master
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (19/19), done.
Writing objects: 100% (19/19), 13.73 KiB, done.
Total 23 (delta 6), reused 0 (delta 0)
To [email protected]:michaelliao/learngit.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
第四步,本地有修改的文件需要提交通过
$ git push origin master
2、 克隆远程库
通过git clone命令克隆远程库到本地
$ git clone <版本库的网址>
$ git [email protected]:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0(delta 0)
Receiving objects: 100% (3/3), done.
3、 git pull(git fetch+merge)
本地与服务器端同步
4、 git push
git push (远程仓库名) (分支名) 将本地分支推送到服务器上去。
5、 git fetch
相当于是从远程获取最新版本到本地,不会自动merge
6、 git rebase
http://www.cnblogs.com/itech/p/5188932.html
五、分支管理
在git里面默认的主分支为master分支,master分支是项目开发的主线分支,为了确保代码最终的一致性,需要我们建立子分支,修改与提交代码,最后合并到主分支,确保主分支代码的统一性。
(一)、创建与合并分支
1. 创建子分支,命名为dev,然后切换到dev分支
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
或者:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b参数表示创建并切换
2. 查看当前分支
$ git branch
* dev
Master
3. 提交当前修改的内容到dev分支
$ git add readme.txt
$ git commit -m"branch test"
[dev fec145a] branch test
1 file changed, 1 insertion(+)
4. 切换到主分支
$ git checkout master
Switched to branch 'master'
5. 将dev分支合并到master分支
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge
命令用于合并指定分支到当前分支
6 删除dev分支
$ git branch -d dev
Deleted branch dev (was fec145a).
(二)、解决冲突
1、场景一:
master主分支与自己创建的子分支都修改了一个文件,导致合并冲突
第一步:创建一个名为feature1的新分支,并切换到当前分支
$git checkout -b feature1
Switched to a newbranch 'feature1'
第二步:修改readme.txt最后一行,改为:
Creating a newbranch is quick AND simple.
第三步:在feature1分支上提交
$git add readme.txt
$ gitcommit -m "AND simple"
[feature1 75a857c]AND simple
1file changed, 1 insertion(+), 1 deletion(-)
第四步:切换到master分支:
$git checkout master
Switched to branch'master'
Your branch is aheadof 'origin/master' by 1 commit.
第五步:在master分支上把readme.txt文件的最后一行改为:
Creating a newbranch is quick & simple.
提交:
$git add readme.txt
$git commit -m "& simple"
[master 400b400]& simple
1 file changed, 1 insertion(+), 1 deletion(-)
现在,master分支和feature1分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突
$git merge feature1
Auto-mergingreadme.txt
CONFLICT (content):Merge conflict in readme.txt
Automatic mergefailed; fix conflicts and then commit the result.
提示readme.txt文件存在冲突,必须手动解决冲突后再提交
第六步:直接查看readme.txt的内容:
Git is a distributed version controlsystem.
Git is free software distributed underthe GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick &simple.
=======
Creating a new branch is quick ANDsimple.
>>>>>>> feature1
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存
Creating a new branch is quick andsimple.
再提交:
$git add readme.txt
$git commit -m "conflict fixed"
[master 59bc1cb] conflict fixed
现在,master分支和feature1分支变成了下图所示:
第七步:用带参数的git log也可以看到分支的合并情况:
$ git log --graph --pretty=oneline--abbrev-commit
* 59bc1cb conflict fixed
|\
| * 75a857c AND simple
* | 400b400 & simple
|/
* fec145a branch test
git log --graph命令可以看到分支合并图
第八步:删除feature1
分支:(强行删除将-d改成-D)
$ git branch -dfeature1
Deleted branch feature1 (was 75a857c).
场景二:
dev子分支开发期间,临时需要修改重大bug,需要创建bug分支,将当前开发期间的dev分支暂存
第一步:暂存工作现场
$ git stash
Saved working directory and index state WIP on dev: 6224937 addmerge
HEAD is now at 6224937 add merge
第二步:切换到master分支,创建临时的bug分支,命名为issue-101,并切换到分支
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master'by 6 commits.
$ git checkout -bissue-101
Switched to a new branch 'issue-101'
第三步:修复对应文件中的bug,例如需要把readme.txt文件内容中“Git isfree software ...”改为“Git is a free software ...”,然后提交:
$ git add readme.txt
$ git commit -m"fix bug 101"
[issue-101 cc17032] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)
第四步:切换到master分支,并完成合并,最后删除issue-101分支
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master'by 2 commits.
$ git merge --no-ff -m "merged bugfix 101" issue-101
Merge made by the 'recursive' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -dissue-101
Deleted branch issue-101 (was cc17032).
第五步:切换到dev分支继续工作
$ git checkout dev
Switched to branch 'dev'
$ git status
# On branch dev
nothing to commit (working directoryclean)
第六步:恢复工作现场
通过git stash list命令,查看已暂存的分支
$ git stash list
stash@{0}: WIP on dev: 6224937 addmerge
恢复有两种方式:
1. 用git stashapply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
2. 用git stashpop,恢复的同时把stash内容也删了:
$ git stash pop
# On branch dev
# Changes to be committed:
# (use "git reset HEAD
#
# new file: hello.py
#
# Changes not staged for commit:
# (use "git add
# (use "git checkout --
#
# modified: readme.txt
#
Dropped refs/stash@{0}(f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
注:如果保存了多个stash,可以恢复指定的stash
通过$ git stash list查看stash列表
stash@{0}: WIP on dev: 6224937 addmerge
恢复:
$ git stash applystash@{0}
(三)、推送分支到远程服务器
$ git push originmaster
$ git push origin dev
哪些分支需要推送,哪些不需要推送
master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步
bug分支只用于在本地修复bug,就没必要推到远程了
六、标签管理
发布一个版本时,我们通常先在版本库中打一个标签,这样,就唯一确定了打标签时刻的版本。
1、 创建标签并操作标签
第一步:切换到需要打标签的分支上
$ git branch
* dev
master
$ git checkout master
Switched to branch'master'
第二步:通过git tag
$ git tag v1.0
查看标签列表
$ git tag
v1.0
查看标签信息
$ git show v0.9
commit622493706ab447b6bb37e4e2a2f276a20fed2ab4
Author: Michael Liao
Date: Thu Aug 22 11:22:08 2013 +0800
add merge
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m"version 0.1 released" 3628164
第三步:删除标签
$ git tag -d v0.1
Deleted tag 'v0.1' (was e078af9)
第四步:推送标签到远程
$ git push originv1.0
Total 0 (delta 0), reused 0 (delta 0)
[email protected]:michaelliao/learngit.git
* [new tag] v1.0 -> v1.0
推送全部标签
$ git push origin--tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 554 bytes,done.
Total 1 (delta 0), reused 0 (delta 0)
[email protected]:michaelliao/learngit.git
* [new tag] v0.2 -> v0.2
* [new tag] v0.9 -> v0.9
第五步:删除远程标签
首先删除本地标签
$ git tag -d v0.9
Deleted tag 'v0.9' (was 6224937)
然后删除远程标签
$ git push origin:refs/tags/v0.9
[email protected]:michaelliao/learngit.git
- [deleted] v0.9
七、忽略特殊文件
以Android项目为例:
Android Studio 中建议过滤的文件:
- .idea 文件夹
- .gradle 文件夹
- 所有的 build 文件夹
- 所有的 .iml 文件
- local.properties 文件
创建本地库,会产生.gitignore文件,这个就是git推送时读取的忽略文件
内容如下:
# Built application files
*.apk
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
# Local configuration file (sdk path,etc)
local.properties
# OSX files
.DS_Store
# Android Studio
*.iml
.idea
# Gradle files
.gradle/
build/
# Local configuration file (sdk path,etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
注:如果遇到我们添加的忽略文件并没有被忽略,可以尝试清一下缓存
git rm -r --cached .
git add .
git commit -m 'update .gitignore'