写给女票的 Git 指南

Git 是啥

首先 git 和 github 不是一个东西。

git 是一个高效的版本控制工具。比如你以前写文档或代码,反反复复修改了很多遍,本地已经存了从 xxx_最终版xxx_打死不改版 的各种文件,你已经不知道每个文件具体修改了啥,想要回到上次修改,也不知该选哪个文件,切占用了大量存储空间 —— git 帮你解决。

git 会保存你每一次提交的版本,你用 git diff 能查看两次提交的修改之处,用 git checkout 可以回退到过去的任意一个版本,你可以在你写的 commit 信息里看到每次提交时的更新信息,你也可以用 git release 发布每一次你认为已经告一段落的工作,更神奇的是,对于两个内容相同的文件,git 只会存储一次,而对于更改较少的内容,git 只会存储修改的部分。

git 只是一个工具,也就是说,git 只是一个可执行程序而不是一个网站。git 的基本单位是文件夹,它会自动识别文件夹下修改的内容,并以合适的方式存储到仓库(一个名为 .git 的隐藏子文件夹)里。安装好 git 之后,你完全可以把仓库放在本地管理,你当然可以把它提交(push)到某个网站上保存。github 就是这样一个网站,当然还有支持免费无限个 private 仓库的 bitbucket 和国产的 coding

安装 Git

安装 git 很简单,对于 windows 用户,下载 Git for Windows 双击安装,对于 Ubuntu 用户,执行 sudo apt-get install git,对于 Mac 用户,执行 brew install git

在本地试试

这一节我们在本地建一个仓库(repository),然后试试如下命令:

1
2
3
4
5
6
git init # 初始化一个仓库
git status # 查看文件修改状态
git add . # 暂存修改的文件
git commit -m "update information" # 提交更改
git log # 查看所有的历史提交
git checkout xxx # 回退到某次提交

初始化仓库

随处新建一个文件夹(如 trygit)作为仓库主文件夹。打开终端(Windows 用户建议打开 Git Bash,安装 Git for Windows 之后自带),进入该文件夹(cd 命令)。然后执行:

1
git init

会提示 Initialized empty Git repository in /.git/。这就表示在 trygit 主目录下新建了一个 git 仓库,里面的所有文件的更改都是可以提交的。来看看 git 仓库的状态:

1
git status

提示 nothing to commit,表示文件夹里没有任何更改(因为木有文件啊)。

提交新版本

trygit 下新建一个 README.txt,再看看仓库状态:

1
git status

会提示 Untracked files: README.txt。表示有未提交的文件 README.txt。我们用 git add 把它添加进来:

1
git add README.txt

再用 git status 看看状态,提示 Changes to be committed: new file: README.txt。所以注意 git add filename1 filename2 ... 只是告诉 git 要把什么文件放加来(暂存,stage),但并未提交到仓库。要用 git commit 提交:

1
git commit -m "initial commit"

-m 后填写关于这次提交的版本说明。这样就把 README.txt 文件放进仓库了。

所以提交更改只需用到两个命令:git addgit commit

TIPs:git add . 或者 git add -A 可以一次添加所有的文件更改。

回退到过去的版本

我们打开 README.txt 添加点文字,如 Hello git。再提交一次:

1
2
git add .
git commit -m "update README.txt"

git log 查看历史提交的版本:

1
git log

会输出:

1
2
3
4
5
6
7
8
9
10
11
commit ffadbc7eb73f23a394903180103886c619970cb1
Author: huanglianghua <withchris@126.com>
Date: Thu Sep 8 11:30:16 2016 +0800
update README.txt
commit 96506e6bbccc097cef55893ae7eb51d847e21905
Author: huanglianghua <withchris@126.com>
Date: Thu Sep 8 11:24:21 2016 +0800
initial commit

可以看到有我们的两次提交,commit 后面的一长串十六进制数字是这次提交的唯一标识符(秘钥)。

现在如果我们想回退到 initial commit 的那次提交,则需要用到对应的密钥,使用 git checkout 命令:

1
git checkout 96506e6bb

你发现我没有把数字串写全对不对?是的,不需要写全,写前面几个数字就可以了。提示 HEAD is now at 96506e6... initial commit 表示回退成功。打开 README.txt 看看,是不是变回空文件(或者你最开始写的内容)了?

总结

OK, 到目前为止你已经学会在本地使用 git 啦。来快速总结一下:

  • 初始化:从命令行 cd 到你想要建立仓库的目录,然后执行 git init 就可以初始化仓库
  • 提交版本:每次更改后 git add -Agit commit -m "message" 就可以提交更改
  • 查看状态:使用 git status 查看仓库状态
  • 查看历史版本:使用 git log 查看所有提交过的版本
  • 切换版本:如果要切换到过去的某次提交,先用 git log 看看那次提交的秘钥,再用 git checkout [秘钥] 退回到这个版本。

在远程试试

这一节把本地的仓库推送(push)到远程仓库。我们将完成身份验证,并尝试命令:

1
2
3
4
5
# 添加远程仓库地址
git remote add origin https://github.com/yourname/trygit.git
git push # 推送本地仓库到远程
git clone # 将远程仓库复制到本地
git pull # 将远程仓库与本地仓库合并

远程提交实际上就是把本地的 .git 文件夹保存到网站(如 Github, Bitbucket 等)上。当然网站自己也会做一些高效的处理,例如,如果你与某个地球对面的美国人写了一份完全一致的 Hello World 程序提交到 Github,那么在 Github 上这份代码只会保存一份,而你们仓库里的文件实际上都是对该代码的引用。

身份验证

git 网站普遍使用 SSH (Secure Shell) 协议来完成身份验证,从而限制只有授权的机器才能更新代码。SSH 的基本要素是一个公钥和一个私钥,git 网站和本地保存一份相同的公钥文件,当推送(push)代码时,会将本地的私钥推送到网站上和公钥匹配以验证推送者的身份。

Github 为例。首先在 Github 官网 注册一个账号,假设注册邮箱为 youremail@mail.com。在本地打开终端(或 Git bash),执行:

1
ssh-keygen -t rsa -C "youremail@email.com"

生成密钥,其中 -C 后的参数是你注册 Github 所使用的邮箱。执行后一路回车(默认路径,不设密码),然后公私钥文件(id_rsa.pub 与 id_rsa)就会存在用户主目录下的 .ssh 文件夹里了。

首先把公钥复制出来。用记事本打开 ~/.ssh/id_rsa.pub 文件复制里面的内容,或者直接执行:

1
cat ~/.ssh/id_rsa.pub | pbcopy

然后把本地公钥粘贴到 Github。打开 Github 网站,点击 头像 -> Settings,然后选择 SSH and GPG keys 一项,点击右边的 New SSH key 按钮添加密钥:

点击 `头像->Settings` 进入用户设置

选择 `SSH and GPG keys` 一项,然后点击 `New SSH key` 按钮

把刚才复制好的密钥粘贴到 Key 对应的框,再给它取个名字(title),如 Company-Notebook,点击 Add SSH Key 按钮保存。这样就完成了密钥生成。接下来设置用户名和邮箱:

1
2
git config --global user.name yourname
git config --global user.email youremail@mail.com

其中 yourname 和 youremail@mail.com 是你注册 Github 是的用户名和邮箱,--global 参数表示全局设置,这样比较方便。以上就完成了 SSH 的设置。在本地测试连接看看:

1
ssh -T git@github.com

你可能会看到警告信息:

1
2
3
The authenticity of host \'github.com (207.97.227.239)\' 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。

如果提示 Hi username! You've successfully authenticated, but GitHub does not provide shell access. 则表示验证成功。

远程提交

在 Github 上点击 New Repository 按钮,创建一个空的仓库,并取个名字(假设为 trygit)。

接下来我们要把本地的 trygit 文件夹里的仓库推送到 Github 的 trygit 上去。cd 到 trygit 目录,首先添加远程仓库地址:

1
git remote add origin https://github.com/yourname/trygit.git

其中 origin 是仓库地址的别名,你也可以取其他的名字。仓库的地址可以进到仓库网页,点击 Clone or download 按钮找到,SSH 或 HTTPS 格式的网址都可以。

然后推送(push)本地仓库到远程:

1
git push -u origin master

命令 -u 表示设置默认的 upstream,这样你下次只需要执行 git push 而无需指定远程仓库地址。出现 Compressing objects:... Writing objects:... 则表示 push 成功。

从远程下载到本地

使用 git clone 命令将远程的代码复制到本地,如复制 Github 上的 torchnet:

1
git clone --recursive https://github.com/torchnet/torchnet.git

其中 --recursive 参数表示递归地复制,有可能在一个 Git 里会引用另一个 Git 作为子模块,该参数可以一次性复制过来。

如果你在多个机器上工作,需要同步内容,或者与其他人协作,则用 git pull,它用于将线上的最新更新同步到本地,只会复制更新的部分下来。

例如你在公司电脑上修改了 trygit 内容并 push 到了 Github 上,而你的家庭电脑保存的旧版本的 trygit。回家后你只需要 cd 到 trygit 目录,执行:

1
git pull

即可同步更新内容。

以上内容足够初步使用 git 了。git 的其他内容如分支(branch)、冲突管理、多远程仓库管理等后续再补充。

么么哒!😘