前言
Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git的读音为/gɪt/。
可以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
本教程部分的内容主要选自廖雪峰Git教程,很容易上手。仅供初学者学习,高手请绕路。
配置用户姓名以及Email
1.用户名和邮箱地址的作用:
- 用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变。
- 每次commit都会用用户名和邮箱纪录。
- github的contributions统计就是按邮箱来统计的。
2.查看用户名和邮箱地址:
$ git config user.name
$ git config user.email
3.修改用户名和邮箱地址:
$ git config --global user.name "username"
$ git config --global user.email "email"
创建版本库
1.mkdir xxx(创建一个本地xxx版本库);
2.pwd (显示当前目录) ;
3.git init(初始化这个目录变成Git可以管理的仓库);
4.ls -ah (查看隐藏的.git文件)。
仓库建好了,是一个空的仓库(empty Git repository),可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git
$ mkdir testgit
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git
$ cd testgit
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit
$ pwd
/e/git/testgit
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit
$ git init
Initialized empty Git repository in E:/git/testgit/.git/
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ ls -ah
./ ../ .git/
提交文件
1.添加文件至仓库的暂存区
- git add <filename> (命令git add把文件添加到仓库);
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git add readme.txt
2.提交暂存区的数据内容
- git commit -m "提交的内容描述" (命令git commit把文件提交到仓库);
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git commit -m "wrote a readme file"
[master (root-commit) d11a667] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
3.多次add不同的文件,commit一次提交很多文件
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
查看当前仓库的状态以及修改内容
1.git status 查看仓库当前的状态
$ git status
2.git diff 查看具体修改了什么内容
$ git diff
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git diff
diff --git a/readme.txt b/readme.txt
index d8036c1..013b5bc 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
\ No newline at end of file
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git add readme.txt
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git commit -m "add distributed"
[master be220b4] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/testgit (master)
$ git status
On branch master
nothing to commit, working tree clean
查看历史记录
1.git log 查看提交历史
2.git log --pretty=oneline 查看提交历史并过滤
3.git reflog 查看命令历史
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/learngit (master)
$ git log
commit 4683cef3c82bac221df5bec4eff97f9367ce5574
Author: Destiny <iamxufeng@users.noreply.github.com>
Date: Wed Mar 15 15:58:21 2017 +0800
Update hello.txt
commit d591d097ff31f7f7af4018c9ee53c30848d2da7d
Merge: 94616bc cd2924b
Author: Destiny <iamxufeng@users.noreply.github.com>
Date: Wed Mar 15 15:44:06 2017 +0800
Merge pull request #1 from iamxufeng/dev
update readme.txt
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/learngit (master)
$ git log --pretty=oneline
4683cef3c82bac221df5bec4eff97f9367ce5574 Update hello.txt
d591d097ff31f7f7af4018c9ee53c30848d2da7d Merge pull request #1 from iamxufeng/dev
cd2924b8097397309a11c15756eff39a4aca7c8a update readme.txt
94616bc9c948a2231380481feea59130a0cc689b add hello
93feb184a2a11777b82dc54e76344938740eba0c add gitignore
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/learngit (master)
$ git reflog
4683cef HEAD@{0}: reset: moving to 4683cef
d591d09 HEAD@{1}: reset: moving to HEAD^
4683cef HEAD@{2}: pull: Fast-forward
d591d09 HEAD@{3}: pull: Fast-forward
cd2924b HEAD@{4}: checkout: moving from d591d097ff31f7f7af4018c9ee53c30848d2da7d to master
d591d09 HEAD@{5}: checkout: moving from dev to origin
cd2924b HEAD@{6}: checkout: moving from master to dev
cd2924b HEAD@{7}: merge dev: Fast-forward
94616bc HEAD@{8}: checkout: moving from dev to master
cd2924b HEAD@{9}: commit: update readme.txt
94616bc HEAD@{10}: checkout: moving from master to dev
94616bc HEAD@{11}: commit: add hello
93feb18 HEAD@{12}: clone: from git@github.com:iamxufeng/learngit.git
回退到上一个版本
HEAD表示当前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一样);上一个版本就是HEAD,上上一个版本就是HEAD,当然往上100个版本写100个比较容易数不过来,所以写成HEAD~100。
1.回到当前版本
$ git reset --hard HEAD
2.回到当前版本的上一个版本
$ git reset --hard HEAD^
3.回到指定的提交ID的版本
$ git reset --hard <commitID>
Administrator@WIN-3CLRCDSGQIC MINGW32 /e/git/learngit (master)
$ git reset --hard HEAD^
HEAD is now at d591d09 Merge pull request #1 from iamxufeng/dev
查看当前文件与版本库中文件的差别
1.git diff HEAD -- <filename> (查看工作区和版本库里面最新版本的区别)
git diff HEAD -- readme.txt
2.工作区修改还原(即修改了本地的文件还没有使用git add 提交到暂存区)
git checkout -- <filename>
可以丢弃工作区的修改
3.从工作区提交到了暂存区(即修改了本地的文件并且使用git add 提交到暂存区)
git reset HEAD <filename>
可以把暂存区的修改撤销掉(unstage),重新放回工作区
git checkout -- <filename>
可以丢弃工作区的修改
4.从暂存区提交到了版本库并且没有推送到远程库(即修改了本地的文件并且使用git add 提交到暂存区,又git commit到版本库)
只能通过版本回退的方式撤销修改:
- 回到当前版本
$ git reset --hard HEAD
- 回到当前版本的上一个版本
$ git reset --hard HEAD^
- 回到指定的提交ID的版本
$ git reset --hard <commitID>
删除文件
1.一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:
$ rm <filename>
2.要从版本库中删除该文件,那就用命令git rm删掉,并且git commit
$ git rm <filename> $ git commit -m "descrition"
例如:
$ git rm test.txt
$ git commit -m "remove test.txt"
3.删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git checkout -- <filename>
例如:
$ git checkout -- test.txt
添加远程仓库
第1步:创建SSH Key。
$ ssh-keygen -t rsa -C "youremail@example.com"
把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
一切顺利的话,可以在用户目录下的.ssh目录中,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面,然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。
1.从远程仓库克隆工程至本地
$ git clone git@github.com:<address>/<project name>.git
例如:
$ git clone git@github.com:iamxufeng/learngit.git
2.把一个已有的本地仓库与远程仓库关联
$ git remote add <远程仓库名 一般写 origin>git@github.com:<address>/<project name>.git
例如:
$ git remote add origin git@github.com:iamxufeng/learngit.git
3.第一次推送master分支的所有内容,把本地库的所有内容推送到远程库上
$git push -u origin master
之后推送最新的修改只需要
$ git push origin master
分支
1.创建分支branch name,然后切换到分支:
$ git checkout -b <branch name>
例如,创建dev分支,然后切换到dev分支::
$ git checkout -b dev
相当于以下两条命令:
$ git branch dev
$ git checkout dev
2.查看当前分支
$ git branch
3.分支的切换
$ git checkout <branch name>
dev分支的工作完成,我们就可以切换回master分支:
$ git checkout master
4.将分支内容与主干分支master合并
- 使用Fast forward合并分支(不建议使用这种方式)
$ git merge <branch name>
必须使用$ git checkout master
切换至master分支,然后在使用$ git merge dev
合并。 - 禁用Fast forward合并分支(推荐使用这种方式)
$ git merge --no-ff -m "descrition" <branch name>
请注意--no-ff参数,表示禁用Fast forward:
$ git merge --no-ff -m "merge with no-ff" dev
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。用git log --graph命令可以看到分支合并图。
5.删除分支
- 删除已经合并过的分支
$ git branch -d <branch name>
例如,删除dev分支:
$ git branch -d dev
- 删除没有合并过的分支
$ git branch -D <branch name>
例如,丢弃一个没有被合并过的分支dev:
$ git branch -D dev
6.查看分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
7.分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
8.把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stash
9.查看存储的工作现场
$ git stash list
10.工作现场的恢复
-
git stash apply
恢复,但是恢复后,stash内容并不删除(使用git stash list 可看到),你需要用git stash drop
来删除 -
git stash pop
恢复的同时把stash内容也删了
11.查看远程库的信息
- 查看远程库的基本信息
$ git remote
- 查看远程库详细信息
$ git remote -v
12.推送分支
git push origin <branch name>
- 推送本地主分支
$ git push origin master
- 推送其他分支
如果要推送其他分支,比如dev:
$ git push origin dev
13.抓取分支
$ git checkout -b <local branch name> origin/<remote branch name>
创建远程origin的dev分支到本地:
$ git checkout -b dev origin/dev
将本地分支dev 推送到远程origin的dev分支
git push origin branch-name
$ git push origin dev
14.提交冲突(即推送失败)
- 先用
git pull
把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送; -
git pull
也失败,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:git branch --set-upstream branch-name origin/branch-name
例如:
$ git branch --set-upstream dev origin/dev
标签
在Git中打标签非常简单,首先,切换到需要打标签的分支上:默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?方法是找到历史提交的commit id,然后打上就可以了:
1.新建标签
git tag <name>
git tag <name> <commitID>
$ git tag -a <name> -m "descrition" <commitID>
例如:
$ git tag v1.0
$ git tag v0.9 6224937
$ git tag -a v0.1 -m "version 0.1 released" 3628164
2.查看标签
$ git tag
查看所有标签
git show <tagname>
查看标签信息
$ git tag
$ git show v0.9
3.推送本地标签
- 推送一个本地标签
git push origin <tagname>
$ git push origin v1.0
- 推送全部未推送过的本地标签
git push origin --tags
4.删除标签
- 删除一个本地标签
git tag -d <tagname>
$ git tag -d v0.1
- 删除一个远程标签
先从本地删除:
$ git tag -d v0.9
再从远程删除。删除命令也是push,但是格式如下:
$ git push origin :refs/tags/v0.9
小结
命令git push origin <tagname>可以推送一个本地标签;
命令git push origin --tags可以推送全部未推送过的本地标签;
命令git tag -d <tagname>可以删除一个本地标签;
命令git push origin :refs/tags/<tagname>可以删除一个远程标签。
参考资料
最后
欢迎大家去 GitHub上Star 和 提Issues,当然,也欢迎留言评论。谢谢大家 !