Git & GitHub 初探
说明
本文章包含以下内容:
- Git - 安装和本地配置
- Git - 文件状态说明
- Git - 常用命令说明
- GitHub - 配置 SSH keys
- GitHub - 创建第一个 GitHub 仓库,并关联本地仓库、提交更改
- GitHub - 处理关联仓库时的冲突
- GitHub - 拷贝远程仓库到本地
- GitHub - 多种方式的总结
Git
安装和本地配置
安装:
- 下载安装包,安装,默认安装了
Git GUI Here
和Git Bash Here
- 需要在哪里使用
git
,只需在文件夹空白处右键,选择Git Bash Here
即可打开git
命令行
本地配置:
// 必须设置邮箱和名字,否则无法 commit
$ git config --global user.email "user_email@example.com"
$ git config --global user.name "user_name"
Git 文件状态说明
nothing to commit, working director clean
:工作区无文件,包括已跟踪和未跟踪Untracked files
:未跟踪的文件,可以使用 add 跟踪文件changes to be commited
:已暂存的修改,此时可以提交,且该版本的文件将会保存在 log 历史记录中changes not staged for commit
:已跟踪的文件修改后未处于暂存区,须再次使用 add 命令使其进入暂存区
Git 常用命令
- 初始化 git
$ git init // 在现有项目中初始化 git
- 查看文件状态
$ git status // 查看当前文件状态
$ git status -s(或short) // 状态简览
- 跟踪文件
$ git add . // 跟踪所有文件,跟踪的文件将会进入暂存区;
$ git add hello.txt // 跟踪单个文件
$ git add *.js // 跟踪所有 .js 后缀的文件
- 提交
$ git commit // 提交修改,并在log中有记录
// 执行此命令会打开一个编辑器,编辑器中按下 Esc 后输入两个大写的 Z 退出编辑
$ git commit -m "commit_word" // 快捷提交,引号内是提交说明
$ git commit -a -m "commit_word" // 将跟踪的文件暂存,并快捷提交
- 推送
$ git push remote-name branch-name // 推送至远程仓库的指定分支
$ git push // 默认推送至 origin 仓库的 master 分支
// 若推送前项目的版本与clone的时候有差别(在你clone之后,push之前有其他人已经push),要先pull拉取更改,合并操作后再push(若有冲突还要解决冲突等操作)
- 拉取
$ git push remote-name branch-name // 从远程仓库的指定分支拉取
$ git push // 默认拉取 origin 仓库的 master 分支的内容
- 查看提交历史
$ git log // 查看所有提交历史
$ git log -p -2 // 显示每次提交的差异,并且只显示最后两次的提交
$ git log stat // 显示每次提交的简略信息
// 提示:大写的 Q 退出 log 命令
// 提示:可以为提交模式设置别名 alias
- 仓库管理
$ git remote // 列出所有指定的远程仓库简写
$ git remote -v // 显示远程仓库的简写及其 URL
$ git remote add <short-name> <url> // 添加远程仓库,并指定别名
$ git fetch <short-name> // 拉取远程仓库中你没有的信息;该命令会拉取至本地仓库,需手动合并
$ git remote show <remote-name> // 列出远程仓库的 URL 与跟踪分支的信息
$ git remote rename <old-name> <new-name> // 更改远程仓库名字
$ git remote rm <remote-name> // 删除指定的远程仓库
- 分支管理
$ git branch // 查看分支
$ git checkout <branch-name> // 切换至指定分支
$ git checkout -b <branch-name> // 创建并切换至分支
$ git branch <branch-name> // 创建分支,但要手动切换
$ git branch -d <branch-name> // 删除分支
GitHub 的使用
配置 SSH keys
- 打开命令行,输入命令
ssh-keygen
生成密钥 - 在 C 盘(C:\Users\你的用户名.ssh)找到
id_rsa.pub
公钥文件,用记事本或其他方式打开文件拷贝里面所有的内容 - 在 GitHub 操作:
Settings
-->SSH and GPG keys
-->New SSH key
--> 粘贴密钥(title可以忽略) -->Add SSH key
创建第一个 GitHub 仓库,并关联本地仓库、提交更改
1)打开 GitHub
主页,点击 New
,创建仓库(这里我没有勾选创建 README
文件):
2)创建完成
由于没有创建 README
文件,当前的仓库是完全空的,然后该仓库页面提示了可以进行的操作:
- 创建一个本地仓库,然后关联推送到远程仓库
- 将已有本地仓库,关联推送到远程仓库
说明:
- 仓库地址:点击红色圈圈可以复制该仓库的地址,左边一行为仓库地址,有
HTTPS
和SSH
两种格式,都可以使用 - 本地仓库:用
git init
在本地创建的仓库,远程仓库就是刚刚在GitHub
创建的hello-world
仓库 - 本地仓库必须要关联远程仓库之后,才能推送本地文件和更改到远程仓库
3)本地仓库的创建
- 创建一个文件夹,在文件夹种打开
Git
命令行,使用git init
初始化Git
仓库:
- 接着在文件夹内创建文件
hello.txt
,随便写点内容,使用git add hello.txt
添加文件到暂存区:
- 提交修改,使用
git commit
输入提交说明:
- 使用
git remote add origin
关联远程仓库:
- 使用
git push
推送至远程仓库:
- 至此,GitHub 仓库已经存储了本地仓库推送的内容,打开 GitHub 仓库,发现一个提交记录:
- 点击进去查看,可以看到提交的信息,和本地
git log
显示的是一样的:
处理关联仓库时的冲突
当关联仓库(git remote add origin
)时,若远程仓库和本地仓库有不一样的提交历史,就会产生冲突;下面记录这种冲突产生的原因以及解决方法。
- 重新创建一个仓库时,同时创建
READEME
文件:
- 此时仓库就不是空仓库了,其中包含了一次提交:
- 点击查看,看到一次初始化提交:
- 复制仓库的地址:
- 创建本地仓库,但是在推送时出现了问题:
仔细想一下,发现远程仓库和本地仓库的文件结构不一样,当推送的时候,git
并不知道我们想要做什么操作(复制还是覆盖、更新);此时先尝试执行 git pull
将远程仓库的内容拉取到本地,结果提示 “没有共同的提交、没有当前分支的跟踪信息” 等信息:
也就是说本地仓库与远程仓库没有向远程仓库提交过信息,不能直接使用 git pull
;接着再尝试执行红框中的命令,其中 <branch>
为需要拉取的远程仓库的分支(没有创建分支时远程仓库只有 master
分支),最后的 master
为本地仓库的分支(本地仓库的默认分支也是 master
);结果显示 “本地仓库的 master
分支已经跟踪远程仓库的 master
分支”:
再尝试执行 git pull
拉取远程仓库的更改时,提示 “拒绝合并不相关的历史”:
这里的意思是远程仓库和本地仓库有不相关的提交历史:初始化远程仓库添加 READEME
文件时有了一次提交,而本地仓库也有一次提交;由于是个人仓库,所以这里可以执行命令 git pull --allow-unrelated-histories
来合并不相关的提交历史(输入该命令时实际会产生一次 merge
,会弹出一个编辑器要求输入提交信息,如果是 Vim 编辑器:输入提交信息后,按下 ESC
后再键入两个大写的 Z
,会退出编辑器并且提交):
最后就可以推送到远程仓库了:
- 在
GitHub
上查看,文件已经推送成功了,并且提交记录变成了三条:
- 查看提交记录,记录是由下至上的(最上面的是最新的):
- 最下面的是初始化仓库的提交
- 再上一条是本地仓库的提交记录
- 最上面的是
merge
操作
也就是说,本地仓库的提交历史和远程仓库提交历史合并了,同时在本地执行 git log
命令也能查看从远程仓库合并的提交历史。
当然,也有一种更为暴力的提交方式:git push origin master -u -f
,这种方式会强制将本地仓库的内容推送到远程仓库,并且会清空远程仓库的提交树,所以应该谨慎使用。
拷贝远程仓库到本地
- 执行
git clone
命令拷贝远程仓库(这里将仓库名重命名为clone-hello
):
- 进入文件目录,创建一个
local-hello.txt
文件,依次执行命令:
- 在 GitHub 中查看仓库,发现文件已经推送上来了:
- 在提交记录中,也看到了本地的提交:
多种方式的总结
关联远程仓库和本地仓库:
- 当远程仓库和本地仓库没有不相关的提交历史时,关联仓库后提交并推送即可
- 当远程仓库和本地仓库有不相关的提交历史时,需要处理它们不相关的提交历史(或者合并),然后再推送并提交
最简单的方式:
- 创建远程仓库后,先不要在远程仓库作任何更改(避免产生不相关的提交历史)
- 使用
git clone
拷贝到本地仓库 - 在本地仓库添加、修改文件
- 提交并推送到远程仓库
最暴力的方式: git push origin master -u -f
,它适用于:
- 初始化仓库
- 提交树混杂,需要清空提交树
- 你很清楚自己在做什么
常见冲突及处理
git clone
拷贝到本地仓库、修改代码、提交代码,但推送时提示冲突:
- 一种情况是,在你执行
git clone
命令后,有人(可能是你也可能是仓库的协作者)在远程仓库修改了某些文件(比如修改了README
),而本地的这些文件跟远程仓库的不相同。这种情况的解决比较简单,先执行git pull
拉取远程仓库(git 会智能地将文件的改动拉取到本地),再执行git push
推送即可。 - 另一种情况是,当
git pull
之后,git push
依旧提示有冲突未处理(并且会将文件从git
工作区删除):这是因为那人在远程仓库修改与你提交的修改都作用了同样的文件(一般开发时会分模块开发,出现的情况较少,但也仍有可能发生),此时git
不知道要听从哪个人的修改。解决方法是手动解决冲突:打开产生冲突的文件(文件里面会标识<<<<<<< HEAD
的下一行就是本地仓库的改动,再接着=======
以下是远程仓库的改动,最后还有>>>>>>>
加上远程仓库的提交哈希串标识),选择性删除代码,并删除上面多出来的标识,重新一套提交流程(因为文件从git
工作区删除,需要重新add
,commit
,push
);当然,也可以选择不删除文件的内容或标识而直接重新一套提交流程将更改提交,但是两个文件的内容和标识都会显示在文件中(有可能会令代码不能工作)。