填写仓库名字,描述可以选填,然后选择Public(只能选Public,意思大家都可以看到,Private是收费版提供的功能)。
Initialize this repository with a README如果勾上,就相当于对仓库做了初始化操作。客户端设置时就需要先git clone下来。这里先不选。
这里给出了SSH的地址。还给出了如何创建一个新的仓库的方法或推送一个已经存在的仓库到Github。
不过在操作之前需要先把公钥送到服务器,否则无法通信。
1
2
3
4
5
6
7
8
|
root@vfeelit:~
# ssh-keygen
Generating public
/private
rsa key pair.
Enter
file
in
which
to save the key (
/root/
.
ssh
/id_rsa
):
Created directory
'/root/.ssh'
.
Enter passphrase (empty
for
no passphrase):
Enter same passphrase again:
Your identification has been saved
in
/root/
.
ssh
/id_rsa
.
Your public key has been saved
in
/root/
.
ssh
/id_rsa
.pub.
|
直接使用ssh-keygen生成秘钥对,提示密码是直接回车表示不使用密码。
把/root/.ssh/id_rsa.pub内容拷贝下来,然后到Github的你的账户设置中设置公钥:
把公钥贴进来。这样,客户端就可以和Github通信了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
root@vfeelit:~
# cd ifeeline/
root@vfeelit:~
/ifeeline
# touch README.md
root@vfeelit:~
/ifeeline
# git init ##初始化,本地生成.git文件夹
Initialized empty Git repository
in
/root/ifeeline/
.git/
root@vfeelit:~
/ifeeline
# git add README.md ##添加任务
root@vfeelit:~
/ifeeline
# git commit -m "first commit" ##添加到版本库
[master (root-commit) f75b3fc] first commit
0 files changed
create mode 100644 README.md
##以上操作在本地完成,然后把本地库和远程进行关联
root@vfeelit:~
/ifeeline
# git remote add origin git@github.com:vfeelit/ifeeline.git
root@vfeelit:~
/ifeeline
# git push -u origin master ##把本地库进行推送
The authenticity of host
'github.com (192.30.252.129)'
can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:
df
:a6:48.
Are you sure you want to
continue
connecting (
yes
/no
)?
yes
Warning: Permanently added
'github.com,192.30.252.129'
(RSA) to the list of known hosts.
Counting objects: 3,
done
.
Writing objects: 100% (3
/3
), 203 bytes,
done
.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:vfeelit
/ifeeline
.git
* [new branch] master -> master
Branch master
set
up to track remote branch master from origin.
|
实验:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
##新建一个文件
root@vfeelit:~
/ifeeline
# vi index.php
root@vfeelit:~
/ifeeline
# ls
index.php README.md
##添加新文件
root@vfeelit:~
/ifeeline
# git add index.php
root@vfeelit:~
/ifeeline
# git status -s
A index.php
##提交新文件
root@vfeelit:~
/ifeeline
# git commit -m "add new file index.php"
[master 68a0842] add new
file
index.php
1
file
changed, 2 insertions(+)
create mode 100644 index.php
##同步到Github
root@vfeelit:~
/ifeeline
# git push -u origin master
Warning: Permanently added the RSA host key
for
IP address
'192.30.252.131'
to the list of known hosts.
Counting objects: 8,
done
.
Compressing objects: 100% (3
/3
),
done
.
Writing objects: 100% (6
/6
), 512 bytes,
done
.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:vfeelit
/ifeeline
.git
f75b3fc..68a0842 master -> master
Branch master
set
up to track remote branch master from origin.
|
从上面操作可知,Github上的是本地的一份镜像,本地修改完毕后需要推送过去。多人协作时可以先克隆下来,然后每人在本地都有一份完整拷贝,修改后进行推送。
github-----github//github-github///
/
1. git 版本控制系统
相比CVS\SVN优势:
- 支持离线开发,离线Repository
- 强大的分支功能,适合多个独立开发者协作
- 速度块
ps:关于git的更详细的介绍于优点在此就不介绍了,教大家怎么用是关键。:)
==============运行环境========
系统:windows
git : Git-1.7.3.1-preview20101002.rar 下载地址:http://d.download.csdn.net/down/3169511/z_y_liu89
===========================
2. github是一个git项目托管网站
注册地址:https://github.com/signup/free
3. 安装git程序,执行下面操作
$ cd ~/.ssh //检查计算机ssh密钥
如果没有提示:No such file or directory 说明你不是第一次使用git,执行下面的操作,清理原有ssh密钥
$ ls config id_rsa id_rsa.pub known_hosts $ mkdir key_backup $ cp id_rsa* key_backup $ rm id_rsa*
获得密钥:
ssh-keygen -t rsa -C "defnngj@gmail.com"//填写email地址,然后一直“回车”ok
打开本地..\.ssh\id_rsa.pub文件。此文件里面内容为刚才生成人密钥。
4. 登陆github系统。点击右上角的Account Settings--->SSH Public keys ---> add another public keys
把你本地生成的密钥复制到里面(key文本框中), 点击 add key 就ok了
5. 接着打开git ,测试连接是否成功
$ ssh -T git@github.com
如果提示:Hi defnngj You've successfully authenticated, but GitHub does not provide shell access. 说明你连接成功了
6. 设置用户信息:
6.1
$ git config --global user.name "defnngj"//给自己起个用户名 $ git config --global user.email "defnngj@gmail.com"//填写自己的邮箱
6.2
在github中找到 Account Settings--->Account Admin ,找到一下信息:
Your API token is e97279836f0d415a3954c1193dba522f ---keep it secret! Changing your password will
generate a new token
$ git config --global github.user defnngj //github 上的用户名 $ git config --global github.token e97279836f0d415a3954c1193dba522f
====================创建一个项目========================
1. 回到github首页,点击页面右下角“New Repository”
填写项目信息:
project name: hello world
description : my first project
点击“Create Repository” ; 现在完成了一个项目在github上的创建。
2. 我们需要使用git在本地创建一个相同的项目。
$ makdir ~/hello-world //创建一个项目hello-world $ cd ~/hello-world //打开这个项目 $ git init //初始化 $ touch README $ git add README //更新README文件 $ git commit -m 'first commit'//提交更新,并注释信息“first commit” $ git remote add origin git@github.com:defnngj/hello-world.git //连接远程github项目 $ git push -u origin master //将本地项目更新到github项目上去
现在查看github上面的hello world 项目,是不是发现已经将本地中的README文件更新上来了。 :) 恭喜!
------------------------------------关于可能出现的错误----------------------------------
1.在执行
$ git remote addorigin git@github.com:defnngj/hello-world.git
错误提示:fatal: remote origin already exists.
解决办法:
$ git remote rm origin
然后在执行:$ git remote add origin git@github.com:defnngj/hello-world.git 就不会报错误了
2. 在执行
$ git push origin master
错误提示:error:failed to push som refs to.......
解决办法:
$ git pull origin master // 先把远程服务器github上面的文件拉下来,再push 上去。
传统VCS的回滚操作
对于版本控制系统VCS来说,回滚这个操作应该是个很普通也是很重要的需求。
如果你是传统VCS,比如SVN或者P4来说,revert是个最直观,也是最直接的手段,当然前提是你的修改还没有被提交到远程的中央仓库。
如果你已经ci了你的code到了远程中央仓库,那revert恐怕也无能为力,只能借助其他命令workaroud这个问题,比如:你用SVN的话,就得来个逆向merge操作,把所有的修改都merge回去。
但这样做也有一些弊端:
这次merge会作为一次全新的commit记录记录下来,也就是说它不能真正从你的历史记录里面抹掉你那次不想要的修改。通常情况下其实也没啥大不了的,除非你个人洁癖就是不想看到以前的那次commit记录或者你真的干了啥不想让别人知道的事情。
Git时代的回滚操作
但当发展到git时代,这种回滚操作的复杂度,已经随着git模型本身的特点,变得不那么简单了。
熟悉git的人都知道,为了分布式的需求,git将每一个网络节点作为了一个完整的VCS,也就是每个单台的host在没有网络的前提下,都是一个不受任何影响可以满足除了和其他节点同步(比如:git pull/push这类)之外的几乎所有操作。
为了达到这种效果,git不仅在本地有一个完整的local repository,而且将原本简单的working tree(或者叫working directory)也切成了两块区域——working tree和index(也叫stage)。
这样,光从本地修改的角度来看,你的修改就可能存在三块区域中,working tree、index或者commit之后的历史对象区域。下面我们一个一个各个区域一般都怎么回滚。
working tree内的回滚
这个属于最简单一种情形,本质上说也是和传统VCS中revert直接对应的一种场景,只是这里不叫revert了,而是git checkout,这种情形很简单,这里就不做截图展示了。列出依稀常用的命令形式如下:
- git checkout file1 (回滚单个文件)
- git checkout file1 file2 ... fileN (一次回滚多个文件,中间用空格隔开即可)
- git checkout . (直接回滚当前目录一下的所有working tree内的修改,会递归扫描当前目录下的所有子目录)
index内的回滚
这部分回滚也不复杂,因为这部分的回滚,只要你勤快点使用git status命令,命令的输出上都会给你提示你需要干啥。只是这个过程一般被分为了两步:
- 将index区域中修改过的文件移除index,也就是恢复到working tree中。这部用git reset来解决。
- 一旦文件重新回到working tree中,回滚操作就是上面提到的git checkout喽。
这个看个截图直观点:
我working tree下的原始文件信息如下
我修改了a.txt和my_dir/b.txt,并将将他们加入了index区域,当前运行git status得到如下输出
这里再执行git reset . 将当前目录及子目录内的所有修改移出index区域,再次运行git status命令
到这一步之后,就用上面提到git checkout就可以解决问题了。
commit之后的回滚
这种情形是git本地回滚里面最复杂,也是最容易让人迷糊的了,因为针对不同的情况,方法比较多,所以不是很好记。
- 修改最后一次commit的记录:很多时候先要回滚仅仅是因为自己对最后一次的commit的漏掉(注意,这里说的漏掉不仅仅是你少提交了文件的修改,也包括你多提交了一下你不想要提交的东西)了一些东西,想要回滚这次commit之后再重新commit。如果是这样的话,没有必要真的非要先回滚再重新commit。只要在在自己已经满意了自己所有的修改之后,直接执行git commit --amend,就可以开启上次提交的“补救”提交模式,然后把你对上次所有漏掉的东西加上去就好了。下面看个例子:我进行了一次错误的提交,修改的内容如下:
目前commit 记录如下:
现在我想补救这次commit,相当于取消这次新加入的文件b.txt、取消对a.txt第三行的修改,然后加入我真正想要的修改:在my_dir下增加一个c.txt,并且修改a.txt的第三行为另外一句话。
再次通过git log查看commit记录
请注意比较最新的一次commit的修改,其实已经被修改为另一个SHA1的值了。这里请注意,从某种意义上说(实际上这种替换在reflog中很容易追踪到痕迹,只是在所有的commit逆向引用链条中,我们已经找不到之前的那个fad4...),这种操作已经做到了无痕修改最后一次提交。这和SVN的逆向merge是本质不同的。 - 回滚中间的某次提交(当然也包括最后一次):比如我想要回滚上图中倒数第二次提交,就是HEAD^那次,我们先通过git show HEAD^看看那次提交都干了啥?
然后再通过git revert HEAD^ 来回滚这次操作,然后我们得到了下面的提示:
杯具,冲突了。。。其实,只要你熟悉任何一种VCS工具,想想这个场景,其实也是挺正常的。那就git status看看哪些个文件冲突了吧。
其实你只要仔细看看上面的说明信息,应该已经知道该怎么解决这个冲突了。明显,a.txt是冲突发生的文件:
打开这个文件,可以看到标准的冲突标识文件。这里正是之前我们采用补救式提交方式修改的那句话。至于冲突怎么解决很容易,看你究竟想要啥了,自己去编辑,去掉冲突范围标识符号,保存文件即可。然后按照git正常的流程再次提交,编辑提交的信息即可。再次提交之后的log信息如下:
上面我们基本上演示了一个标准的revert场景(包括了冲突解决),从这个过程可以看出,git revert和SVN的逆向merge几乎如出一辙,就是将你需要回滚的那次commit所做的所有操作,反向操作一次,然后重新做一一个单独的commit对象进行提交。这个过程是否发生冲突,就取决于你的修改了。请注意,这个过程你虽然回滚了你不想要的修改内容,但是你没法抹掉那次commit在history中的信息,请注意上图的第三行,他依旧坚挺的躺在那里。这个也是git revert的特点。当然,git revert实际上也提供-n(--no-commit)参数,用来表示仅将revert的修改体现在当前的working tree,不自动进行提交。但是如果你真的想回滚那些修改的话,再次commit这个环节是逃不掉的。 - 回滚最后的N次提交(永远从commit的history中抹掉这些记录):这种场景就轮到git reset登场了。git reset的帮助文档写的非常清楚,在回滚commit的场景中,他的作用就是将当前的HEAD reset到你指定的那个分支。但这个过程中最值得注意的就是你使用的参数,最常用的主要是--soft(个人推荐使用这个,他不会修改你目前index或者working tree中所做的任何修改)/--mixed(你在reset时不加任何参数时的默认行为,会默默把你在index中的修改给灭了!)/--hard(这个是我绝的最危险的参数,会把你index和working tree中的所有修改毁灭的毛都不剩,使用之前请三思,这确实是你要的行为!)这三种。因为我推荐使用--soft参数,下面主要演示回滚到3f412...那次的记录(git reset --soft HEAD~2):
从上面可以看出来,你的index区域忽然多了很多未提交的修改,这些就是回滚回来的记录,要怎么处理他们,就看你的了。这时我再来看看log的记录信息:
最新的提交已经变成我们希望的那次了。其实从git reset的解释中,我们就可以看出,git reset是一个“斩断”式的回滚操作,因为你把当前的HEAD指针直接移动到了你需要回滚到的那次记录。而git本身的commit链条是逆向回溯的,所以你在提交历史里面再也找不到当前HEAD指向的commit之后的记录了。(不过如果你是git文艺青年的话,你当然知道,想找到那些表面上找不到的commit,通过reflog也是易如反掌)。
好了,到这里,常用的git回滚操作和场景都介绍完了。希望对不熟悉git的TX能有所帮助。
git reset HEAD //对上一次提交点(所做的操作)进行回滚
git revert和git reset的区别
打标签
同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签。人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。本节我们一起来学习如何列出所有可用的标签,如何新建标签,以及各种不同类型标签之间的差别。
列出已有的标签
列出现有标签的命令非常简单,直接运行 git tag
即可:
$ git tag
v0.1
v1.3
显示的标签按字母顺序排列,所以标签的先后并不表示重要程度的轻重。
我们可以用特定的搜索模式列出符合条件的标签。在 Git 自身项目仓库中,有着超过 240 个标签,如果你只对 1.4.2 系列的版本感兴趣,可以运行下面的命令:
$ git tag -l 'v1.4.2.*'
v1.4.2.1
v1.4.2.2
v1.4.2.3
v1.4.2.4
新建标签
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。
含附注的标签
创建一个含附注类型的标签非常简单,用 -a
(译注:取 annotated
的首字母)指定标签名字即可:
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4
而 -m
选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中。如果没有给出该选项,Git 会启动文本编辑软件供你输入标签说明。
可以使用 git show
命令查看相应标签的版本信息,并连同显示打标签时的提交对象。
$ git show v1.4
tag v1.4
Tagger: Scott Chacon <schacon@gee-mail.com>
Date: Mon Feb 9 14:45:11 2009 -0800
my version 1.4
commit 15027957951b64cf874c3557a0f3547bd83b3ff6
Merge: 4a447f7... a6b4c97...
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sun Feb 8 19:02:46 2009 -0800
Merge branch 'experiment'
我们可以看到在提交对象信息上面,列出了此标签的提交者和提交时间,以及相应的标签说明。
签署标签
如果你有自己的私钥,还可以用 GPG 来签署标签,只需要把之前的 -a
改为 -s
(译注: 取 signed
的首字母)即可:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gee-mail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
现在再运行 git show
会看到对应的 GPG 签名也附在其内:
$ git show v1.5
tag v1.5
Tagger: Scott Chacon <schacon@gee-mail.com>
Date: Mon Feb 9 15:22:20 2009 -0800
my signed 1.5 tag
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)
iEYEABECAAYFAkmQurIACgkQON3DxfchxFr5cACeIMN+ZxLKggJQf0QYiQBwgySN
Ki0An2JeAVUCAiJ7Ox6ZEtK+NvZAj82/
=WryJ
-----END PGP SIGNATURE-----
commit 15027957951b64cf874c3557a0f3547bd83b3ff6
Merge: 4a447f7... a6b4c97...
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sun Feb 8 19:02:46 2009 -0800
Merge branch 'experiment'
稍后我们再学习如何验证已经签署的标签。
轻量级标签
轻量级标签实际上就是一个保存着对应提交对象的校验和信息的文件。要创建这样的标签,一个 -a
,-s
或 -m
选项都不用,直接给出标签名字即可:
$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5
现在运行 git show
查看此标签信息,就只有相应的提交对象摘要:
$ git show v1.4-lw
commit 15027957951b64cf874c3557a0f3547bd83b3ff6
Merge: 4a447f7... a6b4c97...
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sun Feb 8 19:02:46 2009 -0800
Merge branch 'experiment'
验证标签
可以使用 git tag -v [tag-name]
(译注:取 verify
的首字母)的方式验证已经签署的标签。此命令会调用 GPG 来验证签名,所以你需要有签署者的公钥,存放在 keyring 中,才能验证:
$ git tag -v v1.4.2.1
object 883653babd8ee7ea23e6a5c392bb739348b1eb61
type commit
tag v1.4.2.1
tagger Junio C Hamano <junkio@cox.net> 1158138501 -0700
GIT 1.4.2.1
Minor fixes since 1.4.2, including git-mv and git-http with alternates.
gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
gpg: Good signature from "Junio C Hamano <junkio@cox.net>"
gpg: aka "[jpeg image of size 1513]"
Primary key fingerprint: 3565 2A26 2040 E066 C9A7 4A7D C0C6 D9A4 F311 9B9A
若是没有签署者的公钥,会报告类似下面这样的错误:
gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
gpg: Can't check signature: public key not found
error: could not verify the tag 'v1.4.2.1'
后期加注标签
你甚至可以在后期对早先的某次提交加注标签。比如在下面展示的提交历史中:
$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
我们忘了在提交 “updated rakefile” 后为此项目打上版本号 v1.2,没关系,现在也能做。只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可:
$ git tag -a v1.2 9fceb02
可以看到我们已经补上了标签:
$ git tag
v0.1
v1.2
v1.3
v1.4
v1.4-lw
v1.5
$ git show v1.2
tag v1.2
Tagger: Scott Chacon <schacon@gee-mail.com>
Date: Mon Feb 9 15:32:16 2009 -0800
version 1.2
commit 9fceb02d0ae598e95dc970b74767f19372d61af8
Author: Magnus Chacon <mchacon@gee-mail.com>
Date: Sun Apr 27 20:43:35 2008 -0700
updated rakefile
...
分享标签
默认情况下,git push
并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行git push origin [tagname]
即可:
$ git push origin v1.5
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5
如果要一次推送所有本地新增的标签上去,可以使用 --tags
选项:
$ git push origin --tags
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v0.1 -> v0.1
* [new tag] v1.2 -> v1.2
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
* [new tag] v1.5 -> v1.5
现在,其他人克隆共享仓库或拉取数据同步后,也会看到这些标