一、安装Git
在linux上安装Git
- 输入
sudo apt-get install git
,完成git的安装 - 安装完成后输入
git
,出现以下提示说明安装成功
$ git
usage: git [--version] [--help] [-C <path>] [-c name=value]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
在Mac OS X上安装Git
从AppStore安装Xcode,Xcode集成了Git,运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”完成安装
在Windows上安装Git
- 从git官网下载安装程序,安装完成后,在开始菜单里找到“Git”->“Git Bash”,打开命令窗口,说明安装成功
- 安装完成后,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
注:git config命令的--global
参数,表示当前机器上所有的Git仓库都会使用这个配置,也可以对某个仓库指定不同的用户名和Email地址。
二、创建版本库
- 创建一个空目录:
$ mkdir GitTest && cd GitTest
$ pwd
$ /mnt/d/workSpace/GitTest
- 使用
git init
命令,将GitTest
目录变成Git可以管理的仓库
三、 将文件添加到版本库
- 创建一个
README.md
文件,将文件添加到GitTest目录下
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
- 使用
git add
命令将文件添加到git仓库
$ git add README.md
- 使用
git commit
命令将文件提交到git仓库
$ git commit -m "commit README.md file"
[master (root-commit) 2212856] commit README.md file
1 file changed, 1 insertion(+)
create mode 100644 README.md
注:添加文件到Git仓库,分两步:
1. 使用命令git add
,可多次添加多个文件;
2. 使用命令git commit -m
,完成提交。
四、修改文件并提交
- 修改
README.md
文件
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.
- 使用
git status
命令查看运行结果:
$ 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.md
git status
命令可以让我们时刻掌握仓库当前的状态
* 使用git diff
命令可以查看修改过的内容,显示的格式是Unix通用的diff格式
$ git diff
diff --git a/README.md b/README.md
index a2dc532..14c66bf 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
\ No newline at end of file
+Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.^M
+Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.
\ No newline at end of file
- 使用
git add
命令将修改的文件添加到git仓库
$ git add README.md
- 使用
git commit
命令将修改的文件提交到git仓库
$ git commit -m "modify README.md"
[master fef2864] modify README.md
1 file changed, 2 insertions(+), 1 deletion(-)
- 使用
git status
命令查看当前仓库状态
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.idea/
nothing added to commit but untracked files present (use "git add" to track)
五、版本回退
- 使用
git log
命令查看历史版本提交记录
$ git log
commit fef2864a11145c0a38ae45e2f54895a333cd1149
Author: rentuo <johnnyrt@163.com>
Date: Sat Aug 4 15:57:06 2018 +0800
modify README.md
commit 22128561c143caf60baa2ede9c307cb584d4eea9
Author: rentuo <johnnyrt@163.com>
Date: Sat Aug 4 15:34:59 2018 +0800
commit README.md file
- 加上
--pretty=oneline
参数,可以让commit信息合并为一行显示:
$ git log --pretty=oneline
fef2864a11145c0a38ae45e2f54895a333cd1149 modify README.md
22128561c143caf60baa2ede9c307cb584d4eea9 commit README.md file
- 在git中,
HEAD
表示当时当前版本,上个版本表示为HEAD^
,使用git reset
命令回退版本:
$ git reset --hard HEAD^
HEAD is now at 2212856 commit README.md file
- 查看
README.md
的内容,已经被还原:
$ cat README.md
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
- 使用
git log
命令查看历史版本提交记录:
$ git log --pretty=oneline
22128561c143caf60baa2ede9c307cb584d4eea9 commit README.md file
- 还原前的版本已经消失,使用命令
git reflog
命令查看每一次的操作:
$ git reflog
2212856 HEAD@{0}: reset: moving to HEAD^
fef2864 HEAD@{1}: commit: modify README.md
2212856 HEAD@{2}: commit (initial): commit README.md file
- 使用
git reset --hard commit_id
可再次回退到还原前的版本:
t$ git reset --hard fef2864
HEAD is now at fef2864 modify README.md
注:
* HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。
* 穿梭前,用git log
可以查看提交历史,以便确定要回退到哪个版本。
* 要重返未来,用git reflog
查看命令历史,以便确定要回到未来的哪个版本。
六、工作区和暂存区
工作区(Working Directory)
- 自己在电脑中创建的文件夹区域
版本库(Repository)
- 工作区有一个隐藏目录
.git
,是Git的版本库。 - Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
把git往版本库添加分两步:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
创建git版本库时,Git自动为我们创建了唯一一个master
分支,git commit
就是往master分支上提交更改。
每次修改,如果不用git add到暂存区,那就不会加入到commit中;
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。
命令git rm
用于删除一个文件;
七、远程仓库
- Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
- GitHub提供Git仓库托管服务,注册一个GitHub账号,就可以免费获得Git远程仓库。
- 由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,需要生成SSH KEY:
$ ssh-keygen -t rsa -C "youremail@example.com"
- 在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,id_rsa.pub是公钥。
- 登陆GitHub,settings–>SSH and GPG keys:
点“new SSH key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:
添加远程仓库
登陆GitHub,在右上角找到“new repository”按钮,创建一个新的仓库:
在Repository name填入仓库名称,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库:
根据GitHub的提示,在本地仓库运行以下命令:
$ git remote add origin https://github.com/rentuo1/vue-book.git
添加后,远程库的名字就是origin
将本地库的所有内容推送到远程库:
$ git push -u origin master
Username for 'https://github.com': rentuo1
Password for 'https://rentuo1@github.com':
Counting objects: 74, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (68/68), done.
Writing objects: 100% (74/74), 535.74 KiB | 0 bytes/s, done.
Total 74 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), done.
To https://github.com/rentuo1/vue-book.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
- 把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
- 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
- 推送成功后,可以在GitHub页面查看
- 从现在起,只要本地做了提交,就可以通过命令:
$ git push origin master
- 把本地master分支的最新修改推送至GitHub
从远程库克隆
- 使用
git clone
命令克隆一个本地库:
$ git clone https://github.com/rentuo1/vue-book.git
Cloning into 'vue-book'...
remote: Counting objects: 74, done.
remote: Compressing objects: 100% (65/65), done.
remote: Total 74 (delta 3), reused 74 (delta 3), pack-reused 0
Unpacking objects: 100% (74/74), done.
Checking connectivity... done.
八、分支管理
- 假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
- 现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
创建与合并分支
- 创建dev分支
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
- 合并写法:
$ git checkout -b dev
- 使用
git branch
命令查看当前分支:
$ git branch
* dev
master
git branch
命令会列出所有分支,当前分支前面会标一个*号- 在
dev
分支上进行正常的修改提交
$ git add README.md
$ git commit -m "branch test"
[dev 8161bdd] branch test
1 file changed, 1 insertion(+), 1 deletion(-)
dev
分支的工作完成,我们就可以切换回maste
r分支:
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
- 把
dev
分支的工作成果合并到master
分支上:
$ git merge dev
Updating 44505b4..8161bdd
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
git merge
命令用于合并指定分支到当前分支。合并后,再查看README.md
的内容,就可以看到,和dev分支的最新提交是完全一样的。- 注意到上面的
Fast-forward
信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。 - 当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。
- 合并完成后,就可以放心地删除
dev
分支了:
$ git branch -d dev
Deleted branch dev (was 8161bdd).
- 删除后,查看branch,就只剩下master分支了:
$ git branch
* master
- git推荐使用分支
九、解决冲突
- 创建
feature
分支
$ git checkout -b feature
Switched to a new branch 'feature'
- 修改文件并提交
$ git commit -m "feature commit"
[feature 4c4856f] feature commit
1 file changed, 1 insertion(+), 1 deletion(-)
- 切换到
master
分支
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
- 修改
master
代码并提交
$ git add -A
$ git commit -m "master commit"
[master ebc46fc] master commit
1 file changed, 1 insertion(+), 1 deletion(-)
- 当前
master
和feature
都分别有了自己的提交,执行回合
$ git merge feature
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
- Git提示
READM.md
文件存在冲突,必须解决后再次提交 - 使用
git status
命令查看
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
- 查看
README.md
的内容:
$ cat README.md
<<<<<<< HEAD
For detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
=======
for detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
>>>>>>> feature
- 修改后重新提交
$ git add -A
$ git commit -m "conflict fixed"
[master 6a4dfbf] conflict fixed
- 用带参数的
git log
也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
* 6a4dfbf conflict fixed
|\
| * 4c4856f feature commit
* | ebc46fc master commit
|/
* 8161bdd branch test
* 44505b4 my vue-app
- 删除
feature
分支
$ git branch -d feature
Deleted branch feature (was 4c4856f).
十、分支管理策略
- 合并分支时,Git默认会使用
fast forward
模式,这种模式下删除分支后会丢失分支信息 - 强制禁用
Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。 - 使用
--no-ff
方式的git merge
- 创建并切换
dev
分支
$ git checkout -b dev
Switched to a new branch 'dev'
- 修改文件并提交新的
commit
$ git add -A
$ git commit -m "add merge"
[dev 7f98298] add merge
1 file changed, 1 insertion(+), 1 deletion(-)
- 切换回
master
分支:
k$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 4 commits.
(use "git push" to publish your local commits)
- 合并
dev
分支,请注意--no-ff
参数,表示禁用Fast forward:
$ git merge --no-ff -m "merge with no--ff" dev
Merge made by the 'recursive' strategy.
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
- 使用
git log
查看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* cc397ce merge with no--ff
|\
| * 7f98298 add merge
|/
* 6a4dfbf conflict fixed
|\
| * 4c4856f feature commit
* | ebc46fc master commit
|/
* 8161bdd branch test
* 44505b4 my vue-app
- 我们应该按照几个基本原则进行分支管理:
- master分支应该是非常稳定的,仅用来发布新版本,平时不在上边进行开发;
- 在dev分支上进行开发,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
- 每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
- 团队合作的分支看起来就像这样:
十一、bug分支
- 每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
- 当接到修复bug任务、
dev
分支上的工作还未完成无法提交时,可以使用Git提供的stash
功能,将当前工作现场存储起来:
$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge
- 接下来假定基于
master
分支进行bug修复,切换到master
分支,基于master
创建新的分支修复bug后提交并回合master,合并完成后删除修复bug分支 - 切换回
dev
分支继续进行开发 - 使用
git stash list
命令进行查看
$ git stash list
stash@{0}: WIP on dev: f52c633 add merge
- 使用
git stash pop
命令,恢复的同时会删除stash
$ git stash pop
On branch dev
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: hello.py
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
Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)
- 也可以多次使用
git stash
,使用git stash list
查看,恢复的时候指定具体的stash
$ git stash apply stash@{0}
十二、feature分支
- 开发一个新feature,最好新建一个分支;
- 如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除。
十三、多人协作
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功! - 如果
git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
注:
- 查看远程库信息,使用
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 branch
dev
* master
$ git checkout dev
Switched to branch 'dev'
- 使用命令
git tag <name>
就可以打一个新标签,使用git tag
查看:
$ git tag v1.0
$ git tag
v1.0
- 默认标签是打在最新提交的commit上,历史提交的commit忘记打标签,需要找到历史提交的
commitId
打上标签:
$ git log --pretty=oneline --abbrev-commit
7f98298 add merge
6a4dfbf conflict fixed
ebc46fc master commit
4c4856f feature commit
8161bdd branch test
44505b4 my vue-app
$ git tag v0.1 44505b4
$ git tag
v0.1
v1.0
- 使用
git show <tagname>
命令查看标签信息:
k$ git show v0.1
commit 44505b4d935dce8a4e3c7c26ee390c4ea950d944
Author: rentuo <johnnyrt@163.com>
Date: Sat Aug 4 17:33:25 2018 +0800
my vue-app
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..3a280ba
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,12 @@
- 命令
git push origin <tagname>
可以推送一个本地标签; - 命令
git push origin --tags
可以推送全部未推送过的本地标签; - 命令
git tag -d <tagname>
可以删除一个本地标签; - 命令
git push origin :refs/tags/<tagname>
可以删除一个远程标签。
十五、自定义Git
让git显示颜色
$ git config --global color.ui true
忽略特殊文件
- 在Git工作区的根目录下创建一个特殊的
.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。 - 添加一个文件到git无法添加,该文件被
.gitignore
忽略了,可使用-f
命令强制添加:
$ git add -f App.class
- 使用
git check-ignore
命令检查规则问题:
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
配置别名
$ git config --global alias.st status
$ git config --global alias.unstage 'reset HEAD'
- 每个仓库的Git配置文件都放在
.git/config
文件中:
k$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
[remote "origin"]
url = https://github.com/rentuo1/vue-book.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
- 别名在
[alias]
后面,要删除别名,直接把对应的行删掉即可
十六、搭建Git服务器
- 搭建Git服务器需要准备一台运行Linux的机器
- 第一步:安装
git
:
$ sudo apt-get install git
- 第二步:创建一个git用户,用来运行
git
服务 - 第三步:创建证书登录;
收集所有需要登录的用户的公钥,id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。 - 第四步:初始化Git仓库;
先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
$ sudo git init --bare sample.git
- Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
$ sudo chown -R git:git sample.git
- 第五步:禁用shell登录;
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd
文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
- 改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
- git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出;
- 第六步:克隆远程仓库;
- 可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.