Ubuntu或是Debian安装git
sudo apt-get install git
或是直接通过源码安装。先从Git官网下载源码,然后解压,依次输入:./config,make,sudo make install
这几个命令安装就好了。
$ cd ~/.ssh #检查本机已存在的ssh密钥
如果没有,打开终端输入
$ ssh-keygen -t rsa -C "邮件地址"
然后三次回车,生成你的ssh公钥,复制.ssh
目录下的id_rsa.pub
文件的内容,登录github官网,进入个人设置 ->; SSH and GPG keys ->; New SSH
key。将复制的内容粘贴进key那里,title随便填。
$ ssh -T git@github.com # 注意邮箱地址不用改
测试是否成功,碰见问题输入yes,如果终端出现
Hi Anyone! You’ve successfully authenticated, but GitHub does not provide shell access.
代表SSH配置成功,这样可以通过SSH,在本地和github进行数据文件的传输。
安装完成后,还需要最后一步设置,在命令行输入:
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
这是让github确定你的身份。
创建版本库
选定一个文件夹,最好是空的,无其他文件。
git init #创建版本库,把这个目录变成Git可以管理的仓库
git add name #把文件添加进仓库,可反复多次使用,添加多个文件
git commit -m "wrote a readme file" #添加备注,-m后面输入的是本次提交的说明,可以输入任意内容,
当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录
git status #显示当前仓库的状态,显示有没有被修改的文件或是需要提交的文件
git diff #用于比较两次修改的差异
git status
告诉我们,将要被提交的修改包括readme.txt
,下一步,就可以放心地提交了:
$ git commit -m "add distributed"
[master ea34578] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
提交后,我们再用git status命令
看看仓库的当前状态:
$ git status
On branch master
nothing to commit (working directory clean)
干净无文件要提交的工作区。
查看版本
如果改错了文件,找回最近的版本,使用git log查看版本历史
commit 862d2f4d0571faaeb0aa8b8d4f6444616eff6963
Author: denry <835185778@qq.com>
Date: Wed Jan 18 15:20:19 2017 +0800
append GL
commit 9db1540aae0524fc3bf8b6875fa71b94ca448195
Author: denry <835185778@qq.com>
Date: Wed Jan 18 15:17:21 2017 +0800
add distributed
commit 97c79fbf719c3a979aa7106b26e78bb8d78621ff
Author: denry <835185778@qq.com>
Date: Wed Jan 18 15:09:54 2017 +0800
wrote a readme file
(END)
git log
命令显示从最近到最远的提交,如果改的次数多,可以加上--pretty=oneline参数
$git log --pretty=oneline
862d2f4d0571faaeb0aa8b8d4f6444616eff6963 append GL
9db1540aae0524fc3bf8b6875fa71b94ca448195 add distributed
97c79fbf719c3a979aa7106b26e78bb8d78621ff wrote a readme file
(END)
这样看起来就简洁明了了。
你看到的一大串类似 862d2f...ff6963
的是commit id
(版本号),是一个SHA1计算出来的一个非常大的数字,用十六进制表示
退回上个版本
在Git中,用HEAD
表示当前版本,也就是最新的提交862d2f...ff6963
,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
。
$ git reset --hard HEAD^
HEAD 现在位于 9db1540 add distributed
在git log
看一下
commit 9db1540aae0524fc3bf8b6875fa71b94ca448195
Author: denry <835185778@qq.com>;
Date: Wed Jan 18 15:17:21 2017 +0800
add distributed
commit 97c79fbf719c3a979aa7106b26e78bb8d78621ff
Author: denry <835185778@qq.com>;
Date: Wed Jan 18 15:09:54 2017 +0800
wrote a readme file
(END)
恢复最新版本
最初的版本已经消失了,如果想要回去,
只要上面的命令行窗口还没有被关掉,你就可以顺着往上找,找到那个append GPL
的commit id
是862d2f4d...
,于是就可以指定回到未来的某个版本:
$ git reset --hard 862d2f4d057
HEAD 现在位于 862d2f4 append GL
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
然后看一下git log
commit 862d2f4d0571faaeb0aa8b8d4f6444616eff6963
Author: denry <835185778@qq.com>;
Date: Wed Jan 18 15:20:19 2017 +0800
append GL
commit 9db1540aae0524fc3bf8b6875fa71b94ca448195
Author: denry <835185778@qq.com>;
Date: Wed Jan 18 15:17:21 2017 +0800
add distributed
commit 97c79fbf719c3a979aa7106b26e78bb8d78621ff
Author: denry <835185778@qq.com>;
Date: Wed Jan 18 15:09:54 2017 +0800
wrote a readme file
(END)
最新的版本就回来了。
如果你回退到了某个版本,不巧关闭了电脑,找不到以前的新版本的commit id
怎么办?
Git提供了一个命令git reflog
用来记录你的每一次命令:
$git reflog
9db1540 HEAD@{1}: reset: moving to HEAD^
862d2f4 HEAD@{2}: commit: append GL
9db1540 HEAD@{3}: commit: add distributed
97c79fb HEAD@{4}: commit (initial): wrote a readme file
第二条append GL
代表回退前的最新,前面的代表它的commit id。然后
denry:learn/ (master) $ git reset --hard 862d2f4d057
HEAD 现在位于 862d2f4 append GL
工作暂存区
git分为工作区,暂存区,分支区
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
用git diff HEAD -- name.txt
命令可以查看工作区和版本库里面最新版本的区别
git checkout -- file #可以丢弃工作区的修改
git reset HEAD file... # 把文件撤出暂存区,重新放回工作区
只说不好理解,看一张图
删除文件的操作
在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:
$ git add test.txt
$ git commit -m "add test.txt
#[master 94cdc44] add test.txt
#1 file changed, 1 insertion(+)
#create mode 100644 test.txt
在文件管理器删除文件,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:
$ git status
On branch master
Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: test.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且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
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
链接远程仓库
在github网站上刚创建一个远程仓库了learn,进入仓库后,页面会显示
echo "# learn" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:denry/learn.git
git push -u origin master
GitHub
告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub
仓库。添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。
$ git remote add origin git@github.com:denry/learn.git
$ git push -u origin master
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 git@github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
把本地库的内容推送到远程,用git push
命令,实际上是把当前分支master
推送到远程。
由于远程库是空的,我们第一次推送master
分支时,加上了-u参数,Git不但会把本地的master
分支内容推送的远程新的maste
r分支,还会把本地的master分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master
把本地master
分支的最新修改推送至GitHub
,现在,你就拥有了真正的分布式版本库!
小结:
要关联一个远程库,使用命令
git remote add origin git@server-name:path/repo-name.git;
关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容;
克隆
git clone git@github.com:denry/learn.git
分支管理
创建分支并切换
$git branch dev
$git checkout dev
Switched to branch 'dev'
git checkout
命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git checkout -b dev
查看的当前分支
$ git branch
* dev
master
然后,我们就可以在dev分支上正常提交,比如对readme.txt
做个修改,加上一行:
Creating a new branch is quick.
然后提交:
$ git add readme.txt
$ git commit -m "branch test"
[dev fec145a] branch test
1 file changed, 1 insertion(+)
现在,dev分支的工作完成,我们就可以切换回master分支:
$ git checkout master
Switched to branch 'master'
切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
现在,我们把dev分支的工作成果合并到master分支上:
$git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge
命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
合并完成后,就可以放心地删除dev分支了:
$ git branch -d dev
Deleted branch dev (was fec145a).
分支冲突
用git log --graph
命令可以看到分支合并图。
如果我们在feature1
分支修改了readme.tx
t并保存,在master
分支也改了readme.txt
。当
合并分支时
$git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
Git告诉我们,readme.txt
文件存在冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件:
我们可以直接查看readme.txt
的内容:
Git is a distributed version control system. Git is free software distributed under the 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 AND simple.>>>>>>>>> feature1
Git用>>>>>>>>>>>>,=======,>>>>>>>>>>>>>>;
标记出不同分支的内容,我们修改如下后保存:
分支管理策略
准备合并dev分支,请注意--no-ff
参数,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
因为本次合并要创建一个新的commit
,所以加上-m参数,把commit
描述写进去。
合并后,我们用git log
看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* 7825a50 merge with no-ff
|\
| * 6224937 add merge
|/
* 59bc1cb conflict fixed
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并
BUG分支
如果你正在工作着,写了一半的项目,Boss突然让你修复一个bug,手头的项目没有完成不能提交怎么办?幸好,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
命令看看:
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
一是用git stash apply
恢复,但是恢复后,stash
内容并不删除,你需要用git stash drop
来删除;
另一种方式是用git stash pop
,恢复的同时把stash
内容也删了:
你可以多次stash
,恢复的时候,先用git stash list
查看,然后恢复指定的stash,用命令:
$git stash apply stash@{0}
Feature分支
删除一个不再需要且未合并的分支feature-vulcan
git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
销毁失败。Git友情提醒,feature-vulcan
分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用命令git branch -D feature-vulcan
。
现在我们强行删除:
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 756d4af).
多人协作
你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。要查看远程库的信息,用git remote:
$ git remote
origin
或者,用git remote -v
显示更详细的信息:
$ git remote -v
origin git@github.com:denry/learn.git (fetch)
origin git@github.com:denry/learn.git (push)
上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如dev,就改成:
$ git push origin dev
查看远程库信息,使用git remote -v
;
本地新建的分支如果不推送到远程,对其他人就是不可见的。
小结:
从本地推送分支,使用git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交;在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致;建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name
;从远程抓取分支,使用git pull
,如果有冲突,要先处理冲突。
标签管理
git tag name #用于新建一个标签,默认为HEAD,也可以指定一个commit id;
git tag -a tagname -m "blablabla..." #可以指定标签信息;
git tag -s tagname -m "blablabla..." #可以用PGP签名标签;
git tag #可以查看所有标签。
git push origin tagname #可以推送一个本地标签;
git push origin --tags #可以推送全部未推送过的本地标签;
git tag -d tagname #可以删除一个本地标签;
git push origin :refs/tags/tagname #可以删除一个远程标签。
忽略特殊文件
特殊文件就是git无法识别的文件,例如数据库配置文件,word文档等。每次git status
都会显示Untracked files
,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的1.gitignore1文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写1.gitignore1文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了:
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.
如果你确实想添加该文件,可以用-f强制添加到Git:
$ git add -f App.class
或者你发现,可能是.gitignore
写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore
命令检查:
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
总结
思维导图
用网络上找的两张图代替吧,我觉得画的挺好的