介绍Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,2005年开发原型。
git与github有什么区别?
git 是一个版本控制工具
github是一个用git做版本控制的代码托管平台,类似的平台还有bitbucket、oschina的码云
当然(私有化),估计大家还听说过coding、gitlab、gogs、bitbuket,这些都是做一些私有化项目托管的平台。coding是国内做的(鄙人不相信国内的任何东西),gitlab、gogs都是开源的git托管平台,可以自己私有化部署。
git与SVN的区别
SVN 可以理解为版本控制,加上SVN服务器备份的工具,如下图
每个SVN用户可以从服务器checkout代码,同样可以向服务器commit代码,也可以update到别人的代码。
集中管理,操作简单
正因为所有的操作都要基于SVN中心服务器,所以只要SVN中心服务出现冲突(conflict)、错误(error)都会给整个团队之中的成员带来灾难。
git是一种分布式(集成式)的版本控制工具,如下图:
每一个节点都可以充当控制中心的作用,所以从GIT服务器复制(clone)一份到本地,同样也可以单独对自己的本地git版本进行单独管理。在针对单个git版本库的操作(commit,pull)就如同SVN的commit与update操作。当然,不同版本库之间的操作就是拉取(pull),推送(push)。
Git中文件的三种状态
已提交(committed)、已修改(modified)、已暂存(staged)。
已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。
Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。
每个项目都有一个 Git 目录(译注:如果 git clone 出来的话,就是其中 .git 的目录;如果git clone --bare 的话,新建的目录本身就是 Git 目录。),它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
git运行前配置
Git 提供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
/etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用--system 选项,读写的就是这个文件。
~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用--global 选项,读写的就是这个文件。
当前项目的 git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config 里的配置会覆盖/etc/gitconfig 中的同名变量。
在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是C:\Documents and Settings\$USER。此外,Git 还会尝试找寻/etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
git的常用命令
配置用户
git config --global user.name 'xqhero'
git config --global user.email '476837464@qq.com'
如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉--global 选项重新配置即可,新的设定保存在当前项目的.git/config 文件里。
2. 查看配置信息
git config --list
# git config --l
#======result======
user.name=xqhero
user.email=476837464@qq.com
filter.lfs.required=true
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。
也可以直接查阅某个环境变量的设定,如:
$ git config user.name
xqhero
3. 查看帮助
git help config
4. 初始化一个仓库
# 进入一个目录执行
git init
初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。不过目前,仅仅是按照既有的结构框架初始化好了里边所有的文件和目录,但我们还没有开始跟踪管理项目中的任何一个文件。
5. 跟踪一个文件,将一个为跟踪文件写入暂存区
# 添加一个readme.txt
git add readme.txt
添加所有文件采用 git add .
6. 从现有仓库中克隆
git clone git://github.com/schacon/grit.git
如果克隆项目时,需要自定义新建项目的名称,可以这样:
$ git clone git://github.com/schacon/grit.git mygrit
7. 检查文件状态
git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
说明你现在的工作目录相当干净。换句话说,当前没有任何跟踪着的文件,也没有任何文件在上次提交后更改过。此外,上面的信息还表明,当前目录下没 有出现任何处于未跟踪的新文件,否则 Git 会在这里列出来。最后,该命令还显示了当前所在的分支是 master,这是默认的分支名称,实际是可以修改的。
8. 查看已暂存和未暂存的更新
git diff
这个命令是比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
如果想查看已经暂存起来的文件和上次提交时的快照之间的差异,使用:
git diff --cached
9. 提交更新
git commit -m 'add new file'
# git commit
# 不加-m就会进入编辑器进行编写详细内容,格式如下
# 第一行:用一行文字简述提交的更改内容
# 第二行:空格
# 第三行:记述更改的原因和详细内容
10. 直接提交更新
git commit -am 'add a new file'
# -a 参数表示添加到暂存区,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交
11. 移除文件
rm text.txt # 先删除文件
git rm text.txt #然后从跟踪清单中移除
从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。
如果想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中,则使用:
git rm --cached text.txt
此处可以使用glob模式,比如:
git rm log/\*.log
需要注意,在*前加\,因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开(译注:实际上不加反斜杠也可以运行,只不过按照 shell 扩展的话,仅仅删除指定目录下的文件而不会递归匹配)。
12. 移动文件
git mv test.txt a.txt
13. 查看提交的历史记录
git log
git log 只能查看当前状态为终点的历史日志,git reflog 记录最近几个月你的 HEAD 和分支引用的日志。
每次你的分支顶端因为某些原因被修改时,Git 就会为你将信息保存在这个reflog临时历史记录里面。你也可以使用这份数据来指明更早的分支。如果你想查看仓库中 HEAD 在五次前的值,你可以使用引用日志的输出中的@{n} 引用:
$ git show HEAD@{1}
commit 3490ba16674baa83ec13b69c0406e36af1d772de
Author: xqhero <476837464@qq.com>
Date: Mon Jan 9 12:59:21 2017 +0800
add a.txt
diff --git a/a/a.txt b/a/a.txt
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/a/a.txt
@@ -0,0 +1 @@
+a
你也可以使用这个语法来查看一定时间前分支指向哪里。例如,想看你的 master 分支昨天在哪,你可以输入:
$ git show master@{yesterday}
commit 3490ba16674baa83ec13b69c0406e36af1d772de
Author: xqhero <476837464@qq.com>
Date: Mon Jan 9 12:59:21 2017 +0800
add a.txt
想要看类似于 git log 输出格式的引用日志信息,你可以运行 git log -g:
$ git log -g
commit 4cfadc9857ac81cf41bc324dd6a1a440fd5b53f4
Reflog: HEAD@{0} (xqhero <476837464@qq.com>)
Reflog message: commit: update all
Author: xqhero <476837464@qq.com>
Date: Tue Jan 10 13:13:12 2017 +0800
update all
14. 撤销操作
有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用 --amend 选项重新提交。
此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。
git commit --amend
15. 远程库
1) 查看
$ git remote
origin
$ git remote -v
origin https://github.com/xqhero/ADT.git (fetch)
origin https://github.com/xqhero/ADT.git (push)
2) 添加
$ git remote add pb git://github.com/paulboone/ticgit.git
格式为:git remote add [shortname] [url]
3) 抓取数据
$ git fetch pb
fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
$ git pull origin
git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。
4) 推送数据
$ git push origin master
格式为:git push [remote-name] [branch-name]
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。
$ git push -u origin master
# 将当前分支的内容推送到远程仓库origin的master分支。
# -u 参数可以在推送的同时,将origin仓库的master分支设置为本地仓库当前分支的upstream(上游)。添加这个参数后,使用git pull就可以直接从master中获取数据了,省去了另外添加参数的麻烦
5) 查看远程仓库信息
$ git remote show origin
* remote origin
Fetch URL: https://github.com/xqhero/ADT.git
Push URL: https://github.com/xqhero/ADT.git
HEAD branch: master
Remote branch:
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
6) 远程仓库删除与重命名
# rename
$ git remote rename origin org
# delete
$ git remote rm origin
16. 分支
1) 查看分支
$ git branch
* master
* 表示当前所在分支
2) 添加分支,将从当前状态创建新分支
$ git branch test
3) 切换分支
$ git checkout test
M a.php
Switched to branch 'test'
# 切换回上一个分支 git checkout -
4) 创建并切换分支
$ git checkout -b test1
M a.php
Switched to a new branch 'test1'
5) 合并分支 git merge 分支名 ,合并后删除分支将丢失分支信息
$ git merge test1
Updating a9315c4..e62a616
Fast-forward
a.php | 1 +
b.php | 1 +
c.php | 1 +
3 files changed, 3 insertions(+)
create mode 100644 c.php
6) 在历史记录中记录分支合并,禁用fast forward
$ git merge --no-ff test
# git merge –no-ff -m “注释” dev 表示将dev分支合并到所在分支上
7) 删除分支,列表中没有 * 的分支通常都可以用 git branch -d 来删掉。
$ git branch -d test1
Deleted branch test1 (was e62a616).
8) 若要查看各个分支最后一个提交对象的信息
$ git branch -v
* master 56238b3 Merge branch 'test1'
test d6d3e35 Merge branch 'master' into test
test1 f71a0f6 update c.php again
9) 查看与当前分支合并的分支或者还未合并的分支
$ git branch --merge
* master
test1
$ git branch --no-merged
test
删除未合并进来的分区,需要使用:
$ git branch -D test
Deleted branch test (was d6d3e35).
如果想查看未合并分支中哪些提交没有合并,可以使用双点法:
$ git log master..feature-A
# 表示显示feature-A中有,而master中没有的提交
查看你将把什么推送到远程:
$ git log origin/master..master
# 查看当前master分支中有的而远程master分支中没有的提交信息
可以使用^表示提交不包含在分支中,如查找在refA或refB包含而不被refC包含的提交,可以这样:
$ git log refA refB ^refC
$ git log refA refB --not refC
# 两个命令结果相同,表明在refA或refB中包含而不在refC中的提交信息
10) 查看本地分支及远程分支
$ git branch -a
master
* test
remotes/origin/HEAD -> origin/master
remotes/origin/master
17. 回溯历史版本
方法1:
$ git reset --hard HEAD^
# 回退到上一个版本
$ git reset --hard HEAD^^
# 回退到上上个版本
$ git reset --hard HEAD~100
# 回退到前100个版本
方法二:
git reset –hard 2jfkd23
# git reset --hard 版本号
18. 撤销工作区的修改,对新添加的文件无效
$ git checkout -- test.txt
# git checkout -- filename 表示撤销当前工作区的修改
19. stash 隐藏操作
$ git stash
# 把当前工作隐藏起来
$ git stash list
# 查看隐藏的工作
$ git stash apply
# 恢复后,stash内容并不删除,你需要使用命令git stash drop来删除。
$ git stash pop
# 恢复的同时把stash内容也删除
20. tag 标签
$ git tag
# 显示已经有的标签
$ git tag -a v1.1 -m 'my version v1.1'
# 创建一个annotated含附注标签
$ git tag v1.2
# 创建一个轻量级标签
$ git tag -a v1.2 9fceb02
# 可以在任意时间点添加标签
$ git tag -d v1.2
# 删除标签
$ git push origin :v1.2
# 删除远程标签
默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行git push origin [tagname] 即可。
$ git push origin v1.0
# 将v1.0推送到远程库
$ git push origin --tags
# 将所有tag推送到远程库