Git 与 GitHub 入门实践
git配置
优先级:--local > --global > --system
用了
--global
这个参数,表示你这台机器上所有的Git仓库都会使用这个配置 ### 配置git用户名和邮箱
1 | git config --global user.name # 查看 |
仓库
创建git仓库
1 | git init 仓库名 #创建一个git仓库 |
示例:
目录结构:
1 | project |
隐藏目录
.git
不算工作区,而是Git的版本库
查看仓库状态
1 | git status |
远程仓库
最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分
实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交
GitHub就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库,即Github为我们的git仓库提供了一个远程仓库,有了这个远程仓库,妈妈再也不用担心我的硬盘了
为本地与GitHub的通信配置ssh
本地git仓库和GitHub上的远程仓库之间的传输是通过SSH加密的,所以,需要一点设置:
- 创建ssh key:
1
ssh-keygen -t rsa -C "youremail@example.com"
- 登录你的GitHub帐号,
Settings -> SSH and GPG keys -> new SSH key
,将id_rsa.pub的内容复制进去
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送
让本地git仓库和远程仓库同步
在有了本地git仓库后,还需创建对应的远程仓库
- 在GitHub上创建远程仓库(如果已有则省略)
- 为本地仓库设置远程仓库信息(如果同时需要为本地仓库添加多个远程仓库(如果github+码云),则可以将
origin
分别换成github
和gitee
,推送操作时也要修改origin
。添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库)1
git remote add origin https://github.com/用户名/仓库名
- 删除本地仓库的远程仓库信息:
git remote remove origin
- 修改远端地址:
git remote set-url 新地址
- 查看远程仓库信息:
git remote -v
- 删除本地仓库的远程仓库信息:
- 将本地git仓库push到远程仓库
1
2
3
4# 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的
# master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master
# 分支关联起来,在以后的推送或者拉取时就可以简化命令
git push [-u] origin 分支名
并不是一定要把本地分支往远程推送。哪些分支需要推送、哪些不需要呢?
master
:主分支,要时刻与远程同步dev
:开发分支,团队所有成员都需要在上面工作,所有也需要与远程同步bug
:只用于在本地修复bug,就没必要推送到远程了,除非老板要看看你每周修复了几个bug
协同工作
拉取分支:
1 | git pull |
git clone
时,默认情况下只能看到本地的master
分支。如果要在dev
分支上开发,就必须创建远程origin
的dev
分支到本地,可以使用如下命令创建本地dev
分支:
1 | git checkout -b dev |
将本地dev
分支与远程origin/dev
分支关联起来:
1 | git branch --set-upstream dev origin/dev |
使用GitHub
Bootstrap的官方仓库twbs/bootstrap、你在GitHub上克隆的仓库my/bootstrap,以及你自己克隆到本地电脑的仓库,他们的关系就像下图显示的那样:
如果你想修复bootstrap的一个bug,或者新增一个功能,立刻就可以开始干活,干完后,往自己的仓库推送
如果你希望bootstrap的官方库能接受你的修改,你就可以在GitHub上发起一个pull request。当然,对方是否接受你的pull request就不一定了
版本控制
隐藏目录.git
不算工作区,而是Git的版本库。版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区。还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
添加或删除修改
将修改添加到暂存区:
1 | git add 文件/目录 |
从暂存区删除修改:
1 | git rm --cached 文件/目录 |
以下命令可以将暂存区的修改重置,暂存区的改变会被移除到工作区:
1 | git reset HEAD [文件名] |
以下命令可以丢弃工作区的修改:
1 | git checkout -- [文件名] |
如果刚对一个文件进行了编辑,可以撤销文件的改变,回到编辑开始。命令其实起到“一键恢复”的作用,还可用于“误删恢复”。可以在 git reset HEAD [文件名]
后使用
提交版本
如果修改了readme.txt,添加了文件LICENSE,并将2者添加到暂存区后,暂存区的状态就变成这样:
使用commit提交修改,实际上就是把暂存区的所有内容提交到当前分支:
1 | git commit -m '信息' |
commit相当于游戏里面一次存档。对应一个版本
文件删除
rm
做出的删除不会被暂存,git rm
做出的改变会被暂存。如果使用rm
删除掉,能使用git rm
来暂存。git rm
不在意文件已经不存在了
删除(暂存)单个文件
1
git rm
删除(暂存)多个文件(一般情况下,更可能是对大量文件进行管理。可能同时会删除很多文件,不可能使用
git rm
一个个删除)1
2# 它会变量当前目录,将所有删除暂存
git add -u .
如果有文件被误删,可以使用git checkout -- 文件名
恢复
工作现场保存与恢复
有时候在修复bug或某项任务还未完成,但是需要紧急处理另外一个问题。此时可以先保存工作现场,当问题处理完成后,再恢复bug或任务的进度
- 保存工作现场:
git stash
- 查看保存的工作现场:
git stash list
- 恢复工作现场:
git stash apply
- 删除stash内容:
git stash drop
- 恢复工作现场并删除stash内容(相当于上面2步合并):
git stash pop
改动查询
1 | git diff [选项] # 查看工作区中的修改 |
版本回退
1 | git reset --hard 版本ID/HEAD形式的版本 |
如果回到过去的版本,想要回到原来新的版本:
- 如果终端未关,可以找到新版本的id,通过上述命令回去新版本
- 如果终端已关,
git reflog
查看版本,再通过上述命令回去新版本
查看历史提交
1 | git log [选项] |
加文件名可以显示具体文件相关的所有提交信息
分支管理
创建与合并分支
每次commit
相当于一次存档,对应一个版本。Git都把它们串成一条时间线,这条时间线就是一个分支。master
就是主分支。HEAD
指向当前分支,而master
指向主分支的最近提交。每次提交,master
分支都会向前移动一步
当创建一个分支时,如dev
,Git创建一个指针dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:
上面的合并使用的是Fast forward。这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的提交,这样,从分支历史上就可以看出分支信息。通过在git merge
命令中使用--no-ff
选项禁用Fast forward模式。比如在合并dev
时:
1 | git merge --no-ff -m "merge with no-ff" dev |
由于会生成一个新的提交,所以需要使用-m
指明新提交的信息。此时分支情况如下:
相关命令如下:
- (创建分支并)切换到新分支:
git checkout -b 新分支
- 创建分支:
git branch 新分支
- 切换分支:
git checkout 欲切换到的分支
- 查看当前分支:
git branch
- 合并某分支到当前分支:
git merge 欲合并到当前分支的分支
- 查看历史分支情况:
git log --graph --pretty=oneline --abbrev-commit
- 删除未合并的分支:
git branch -D 分支
分支合并冲突
如果两个分支修改了同一文件,合并时会发生冲突。比如master
分支和feature1
分支都修改了readme.txt
文件,各自都有新的提交:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。此时readme.txt
文件会变成如下形式:
1 | Git is a distributed version control system. |
Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,此时需要手动修改后保存。然后再使用git commit
进行一次提交。分支会变成如下:
分支管理策略
在实际开发中,我们应该按照几个基本原则进行分支管理
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活
干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了
所以,团队合作的分支看起来就像这样:
当你从远程仓库克隆时,实际上Git自动把本地的master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
要查看远程库的信息,用git remote
:
1 | $ git remote |
或者,用git remote -v
显示更详细的信息:
1 | $ git remote -v |
上面显示了可以抓取和推送的origin
的地址。如果没有推送权限,就看不到push的地址
推送分支
1 | git push origin 欲推送的分支 |
master
分支是主分支,因此要时刻与远程同步dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步bug
分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bugfeature
分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发
Git 与 GitHub 入门实践