学习 git 之前需要先了解git 的几个概念:
Workspace:工作区
Index / Stage:暂存区
Repository:仓库区(或本地仓库,版本库)
Remote:远程仓库
1. 配置Git信息
第一个要配置的是你个人的用户名称和电子邮件地址。这两条配置很重要,每次 Git 提 交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:
git config --global user.name "your name"
git config --global user.email "your email"
如果用了 --global 选项,那么更改的配置文件是在~/.gitconfig里的配置,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或 者电邮,只要去掉 --global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
查看配置信息
要检查已有的配置信息,可以使用 git config --list 命令:
$ git config --list
user.name=shixiangyu
user.email=shixiangyu@gmail.com
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:
$ git config user.name
shixiangyu
2. 仓库
2.1 仓库的创建
有两种取得 Git 项目仓库的方法。第一种是在现存的目录下,通过导入所有文件来创建 新的 Git 仓库。第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来。
- 从当前目录初始化
要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:
- 从当前目录初始化
git init
初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都 存放在这个目录中。不过目前,仅仅是按照既有的结构框架初始化好了里边所有的文件和目 录,但我们还没有开始跟踪管理项目中的任何一个文件。
- 从远程仓库克隆
克隆仓库的命令格式为 git clone [url]。比如,要克隆 下面这个 Git 仓库 ,可以用下面的命令:
- 从远程仓库克隆
git clone git://github.com/schacon/grit.git
如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令最后指定:
git clone git://github.com/schacon/grit.git mygrit
唯一的差别就是,现在新建的目录成了 mygrit,其他的都和上边的一样。
- 关联远程仓库
这是在本地已有仓库的情况下,需关联到远程某个仓库,一般情况下这个远程仓库是空的,可以通过命令git remote add <主机名> <网址>
进行关联,如:
- 关联远程仓库
git remote add origin git://github.com/schacon/grit.git
- 仓库地址的变更
此种情况一般发生在项目的迁移时会用到,远程仓库的地址发生了变更,这时候需要在本地仓库也要进行地址的更新
- 仓库地址的变更
git remote set-url origin git://github.com/schacon/grit..git
2.2 记录每次更新到仓库
检查当前文件状态
要确定哪些文件当前处于什么状态,可以用 git status 命令。如果在克隆仓库之后立即 执行此命令,会看到类似这样的输出:
$ git status
# On branch master
nothing to commit (working directory clean)
这说明你现在的工作目录相当干净。换句话说,当前没有任何跟踪着的文件,也没有任何 文件在上次提交后更改过。此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪 的新文件,否则 Git 会在这里列出来。最后,该命令还显示了当前所在的分支是 master, 这是默认的分支名称。
查看当前的远程库
要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短 名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个 名字来标识你所克隆的原始仓库,origin和当前仓库的地址对应。
$ git remote
origin
也可以加上 -v 选项(译注:此为 —verbose 的简写,取首字母),显示对应的克隆地 址:
$ git remote -v
origin git://github.com/schacon/ticgit.git
那么origin这个名字可以自己指定吗,当然可以,在clone仓库的时候,加个 -o 参数进行指定,如
git clone -o grit git://github.com/schacon/grit..git
此时再执行命令git remote:
$ git remote
grit
"grit" 便代替了git默认指定远程主机名 "origin"
当然后期也能对仓库主机名进行变更,不过工作中一般并用不到,都是默认的origin,可作了解:
git remote rm <主机名>
用于删除远程主机。
git remote rename <原主机名> <新主机名>
用于远程主机的改名。
3 分支
3.1新建分支
Git 是如何创建一个新的分支的呢?答案很简单,创建一个新的分支指针。比如
新建一个 testing 分支,可以使用 git branch 命令:
$ git branch testing
这会在当前 commit 对象上新建一个分支指针
那么,Git 是如何知道你当前在哪个分支上工作的呢?其实答案也很简单,它保存着一 个名为 HEAD 的特别指针。请注意它和你熟知的许多其他版本控制系统(比如 Subversion 或 CVS)里的 HEAD 概念大不相同。在 Git 中,它是一个指向你正在工作中的本地分支的 指针。运行 git branch 命令,仅仅是建立了一个新的分支,但不会自动切换到这个分支中 去,所以在这个例子中,我们依然还在 master 分支里工作
要切换到其他分支,可以执行 git checkout 命令。我们现在转换到新建的 testing 分支:
$ git checkout testing
这样 HEAD 就指向了 testing 分支
创建新分支和切换到该分支可不可以合并成一条命令,当然可以。要新建并切换到该分支,运行 git checkout 并加上 -b 参数:
$ git checkout -b new_branch
3.2 查看分支
要查看当前仓库下的所有本地分支,可以执行git branch 命令,会把本地名列出来:
$ git branch
* master
testing
new_branch
加上 -r 选项(此为 -remote的简写),参看的是远程的所有分支:
$ git branch -r
origin/master
origin/testing
加上 -a 选项的话,会把本地和远程的所有分支列举出来,相当于上面两条命令的合并:
$ git branch -a
* master
testing
new_branch
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/testing
加上 -vv 选项(是两个字母v),会列出所有本地分支以及它们已经关联的远程分支,即本地分支的上游分支:
$ git branch -vv
* master 5dffada [origin/master] 新增test方法
testing 6dffa62 [origin/testing] TestBranchActivity增加onCreate方法
new_branch 5dffada 新增test方法
可以看到本地master分支的上游分支是origin/master,testing分支的上游分支是origin/testing,而new_branch 尚未关联远程分支,即不存在它的上游分支,就目前而言它只是一个存在于本地仓库的分支,远程仓库上还没有这个分支。
当然,我们可以通过·git push
命令来向远程仓库推送这个本地的新分支,如果你不太守规矩,直接在新分支上执行了git push 命令,可能会提示你:
$ git push
fatal: The current branch new_branch has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin new_branch
提示的够简单粗暴,现在的分支new_branch还没有上游分支,如何解决,下面说。
3.3 推送和拉取分支
本地提交完更改后,此时只是将更改commit到了本地仓库中,对远程仓库还没有任何影响,这时我们可能会通过 git push 命令需要将变更推送到远程仓库上:
$ git push <远程主机名> <本地分支名>:<远程分支名>
注意: 命令中的本地分支是指将要被推送到远端的分支,而远程分支是指推送的目标分支,即将本地分支合并到远程分支。
如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建:
$ git push origin master
上面命令表示,将本地的master分支推送到origin主机,由于没有指定远程分支名,默认推送到远程仓库origin的master分支上,如果远程仓库origin上不存在master分支,则会被新建。
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支,这条命令是删除远程master分支。
$ git push origin :master
# 等同于
$ git push origin --delete master
如果当前分支有上游的跟踪分支,那么主机名和本地分支名都可以省略:
$ git push
问题来了,如果当前分支不存在上游分支,直接执行git push 命令是推送不成功的,上面也提到了,当然,如果你够守规矩,通过git push <远程主机名> <本地分支名>
的方式是可以推送的,远程仓库如果没有这个分支,会自动创建一个和这个本地分支同名的一个新分支。比如我们来推送new_branch这个本地新分支
$ git push origin new_branch
* [new branch] new_branch -> new_branch
成功推送,但以后工作中,我们在提交代码的时候都要在git push命令后加上origin new_branch参数,多麻烦,这时候我们就可以通过--set-upstream-to
命令为一个本地分支关联一个上游分支了:
git branch --set-upstream-to=<远程主机名>/<远程分支名>
也可以简写为
git branch -u <远程主机名>/<远程分支名>
如我们为new_branch分支关联一个远程分支
$ git branch --set-upstream-to=origin/new_branch
注意,你可以把一个本地分支和任意一个存在的远程分支进行关联,不过一般和同名的分支进行关联
那么,在第一次推送一个新分支的时候就去为它关联一个远程分支是不是可以在一条命令完成,当然可以:
$ git push --set-upstream origin new_branch
或
$ git push -u origin new_branch
这两条命令效果一样,标识将本地分支new_branch推送到远端origin仓库,并设置new_branch的上游分支为 origin/new_branch。
3.4 分支重命名
git branch -m new_name
注意:重命名的是当前分支
4. 撤消操作
4.1 修改最后一次提交
有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才 的提交操作,可以使用 --amend 选项重新提交:
git commit --amend
此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,而所提交的文件快照和之前的一样。
启动文本编辑器后,会看到上次提交时的说明,编辑它确认没问题后保存退出,就会使用新的提交说明覆盖刚才失误的提交。
如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交:
git commit -m 'initial commit' //提交后发现少提交了 一个文件
git add forgotten_file
git commit --amend
4.2 回退本地版本库
HEAD或HEAD~0,指向最近的一次提交,HEAD^或HEAD~1指向最近一次的上一次提交版本,有点绕,但容易理解,以此类推。
git reset --hard HEAD~1
回退一个版本,清空暂存区,将已提交的内容的版本恢复到本地,本地的文件也将被恢复的版本替换
如果只是想回退一个版本,不清空暂存区,将已提交的内容也恢复到暂存区,不影响原来本地的文件(未提交的也不受影响)
git reset --soft HEAD~1
5.其他
打开 git 的图形界面,可完成add与commit功能,这个命令可能会成为你以后工作当中经常使用的命令(该命令只在windows下可用):
git citool
查看提交历史,可打开提交历史面板(该命令只在windows下可用)
gitk
给分支打Tag
新建Tag:
git tag tag_name
把新建的Tag 推送到远端服务器:
git push origin tag_name
删除Tag
(1)删除本地Tag
git tag -d tag_name
(2)删除远端服务器Tag
git push origin :refs/tags/tag_name