如何使用git这一高效代码管理工具
如何使用github这一最大的软件开源社区
1.github
1.1github简介
(仓库)repository:
项目代码的储存
一个项目一个repository,多个项目多个repository
(收藏)star:
收藏项目,方便下次查看
(复制克隆)Fork:
把别人的仓库完整的复制一份到我的新建仓库,该fork项目独立存在
使用者Fork开发者的一个仓库的时候,会生成一个连仓库名都一样的一个仓库
(发起请求)pull request:
当我对fork后的repository进行了修改,该更新动作可以通过pull request发起请求提交给项目拥有人审核,通过即可并入原项目
(关注)watch:
类似社交软件的关注,此时项目的新动作可以接收通知
(评论)issue:
体现同性交友平台这一基本属性
1.2github操作
文件操作
create new file:
就相当于在仓库里 touch了一个新的文件a. 文件名
b. 文件内容:
c. 表单:填写每次提交的目的(让其他开发者知道本次添加或修改的原因)
编辑和修改文件:
a. 点击文件名可以查看该文件详细信息
b. 点击铅笔图标可以修改文件
删除文件:
点垃圾桶图标
仍会保留commit,可以查看删除信息
上传文件(upload):
选择点击或拖拽,比通过git命令行方便些
筛选查看文件(go to file):
可以根据关键字快速匹配之前的文件
项目下载(clone): 项目下载到本地
开源项目贡献流程
提出issues
pull request
a. fork项目
b. 修改自己仓库的项目代码
c. 新建pull request
d. 等待项目管理员审核
1.3项目索引方法
通过在索引框中添加限制条件,让搜索结果更接近自己想要的项目
常用的有仓库标题,项目描述等。。
参考链接(简书):江湖必点的小菜
2.git
2.1快速安装
等官网下载完怕是要下辈子了,这里使用淘宝镜像下载
6-12更新:右键找不到git bash here选项时应如何配置!!!
https://blog.csdn.net/weixin_42357048/article/details/80533571
2.2git配置(必须进行)
Git 提供了一个叫做 git config 的工具,专门用来配置或读取相应的工作环境变量。
这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用git config
时用--system
选项,读写的就是这个文件。~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用git config
时用--global
选项,读写的就是这个文件。当前项目的 Git 目录中的配置文件(也就是工作目录中的
.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。也即越往项目内层靠近,config的优先级越高
a.配置用户信息(必须)
1 | $ git config --global user.name "runoob" |
如果用了 —global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。一次设置终身使用(本机)
如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 —global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
b.差异分析工具(可选)
在解决合并冲突时使用哪种差异分析工具
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。
c.查看配置信息
1 | $ git config --list |
2.3如何使用
a.初始化一个新的git仓库
- 新建一个文件夹:mkdir test
- 路径改到当前文件夹下:cd test
- 初始化:git init(创建一个新的git仓库)
b.向仓库添加文件、文件夹
- 向工作区创建文件:touch+文件名(test.py)
将文件提交到暂存区:git add+文件名
添加文件夹:git add +文件夹/
添加某类型文件:git add+*.文件类型
添加当前文件夹下全部文件(包括子目录):git add —all
git add命令描述:
git add -A和 git add . git add -u在功能上看似很相近,但还是存在一点差别
git add .:他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。
git add -u :他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。add -u
不会提交新文件(untracked file)。(git add --update的缩写)
git add -A :是上面两个功能的合集(git add --all的缩写)
c.查看仓库信息
查看当前工作区的全部文件:git ls-files
查看当前工作区的状态变化:git status
只想看工作区里哪些文件变化:git status -s
问题1:执行了git add,git status仍然clean
原因:
文件的修改日期早于最后一次的commit,此时再提交add能够检测到文件未发生改变,即不是新文件
git status监视的是工作区的变动。
问题2:git显示文件名都是数字(中文乱码)
解决:git config --global core.quotepath false
d.管理/放弃修改(status)
每次修改都得git add到暂存区,不然不会commit到仓库
git checkout -- file
可以丢弃工作区的修改 (当然包括删除文件的恢复):- 一种是
readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; - 一种是
readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
- 一种是
git reset HEAD <file>
可以把暂存区的修改撤销掉(unstage),重新放回工作区以git status为例:
当工作区发生变化(文件内容变动),但还没有add的时候
1
2
3
4
5
6
7
8
9
10
11$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: git和github教程.md
modified: markdown用法.md
no changes added to commit (use "git add" and/or "git commit -a")可以看到git检测到了工作区的变化,但是提醒你没有staged(),没法提交!
此时可以执行两类操作:
1.撤销变动(慎用,会把该文件上次commit后的全部修改作废):
git checkout -- file
2.add到暂存区
当你已经执行了add或者
git rm -r cached .
等会改变暂存区状态的操作想要撤销:git reset HEAD <file>
e.版本回退(commit)
每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit
。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
- 通过git log查看commit历史,详情见2.4,想回到过去就需要git reflog查看命令历史
- Git必须知道当前版本是哪个版本,在Git中,用
HEAD
表示当前版本,也就是最新一次的commit09d1e67...
,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。- 回溯到上1个版本:
git reset --hard HEAD^
- 回溯到上10个版本:
git reset --hard HEAD~10
- 回溯到指定版本号(往前往后都行):
git reset --hard 1094a
- 回溯到上1个版本:
注意:回溯历史的版本,再用git log就看不到之后的版本了,只能用git reflog
f.删除仓库文件
从git中删除文件:
1
git rm <file>
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f:
1
git rm -f <file>
如果把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 —cached 选项即可
1
2git rm --cached <file>
或者:git reset HEAD <file>可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:
1
git rm –r *
进入某个目录中,执行此语句,会删除该目录下的所有文件和子目录。
删除仓库
rm -rf .git
g.移动或重命名一个文件、目录
以重命名为例:
1 | $ git mv README README.md |
2.4查看提交历史/比较区别
- git log 查看提交历史 如下:
1 | Administrator@SD-20200530BSYV MINGW64 /f/a_repository (master) |
我们可以用 —oneline 选项来查看历史记录的简洁的版本。
—reverse —online可以逆向显示
1 | git log --oneline |
可以用 —graph 选项,查看历史中什么时候出现了分支、合并。以下为相同的命令,开启了拓扑图选项:
1
2
3
4
5
6
7git log --graph
* commit a1da438ef8cc3d075b5c0a0b8e47c94e23f60272 (HEAD -> master, origin/master)
| Author: biongd <862991505@qq.com>
| Date: Tue Jul 21 16:40:07 2020 +0800
* commit a1da438ef8cc3d075b5c0a0b8e47c94e23f60272 (HEAD -> master, origin/master
|
| 数据结构与算法.md.git diff
比较两个commit差异 可以看到这是从第二次提交的内容中找和第一次不同的地方严格来说应该是第二次提交后,分支的内容与上一次后的分支内容有哪些变化
1 | $ git diff 39474be a1da438 |
2.5 git bash 中文显示为数字的问题
如上所示:文件名中的中文均被数字和斜杠代替,解决方法如下:
git config —global core.quotepath false//注意是2个”-“
2.6 当近端和远程发生冲突
如果是同一个分支,一般会采用 pull rebase 进行合并,即不会形成新的提交点。而默认 git pull 是通过 merge 合并。
如果发生冲突的话,无论是 merge,还是 rebase,都需要先解决冲突,这个过程需要通过手动解决。比如发现一个文件发生冲突。手动解决完冲突后,用 git add 把处理好的内容提交到暂存区。接下来的处理,merge 和 rebase 的操作不同。
如果是 merge,通过 git commit 即可。如果是 rebase,通过 git rebase —continue,继续执行 rebase 即可。
一个简单的例子。
假设 pull 之后,某个文件内容如下
1 | <<<<<<< HEAD |
我们需要手动解决文件冲突,修改之后的内容如下:
1 | const a = 1 |
接着,执行 git add 把文件提交到暂存区,接着通过 git commit 提交到仓库,最后,通过 git push 提交到远程。假设是 rebase,只需要将 git commit 修改为 git rebase —continue 即可。
3.git和github远程仓库
既可以通过https协议访问github,也可以通过添加ssh key(本机秘钥)来访问,推荐使用ssh key,可以不用输入账号密码验证
3.1从远程仓库的项目克隆到本地:
git:git clone+仓库地址(https或者SSH)
3.2添加秘钥及远程库
1.添加ssh key
ssh-keygen -t rsa -C "youremail@example.com"
邮箱用处不大随便填就好,然后一路默认就行(别乱填,不然容易出错),成功的话会在C:\user\administrator下生成 .ssh 文件夹,打开 id_rsa.pub,复制里面的 key。回到github或码云的个人头像setting,找到ssh and GPG keys 粘贴进去
2.检查key有没有有效添加(能否成功连上github)
1 | $ ssh -T git@github.com |
3.添加远程库
git remote add [shortname] [url]
3.3将本地仓库同步到git远程仓库:
1 | git init |
3.4查看当前的远程库
1 | $ git remote |
3.5提取远程仓库更新
1 | 1.从远程仓库下载新分支与数据:git fetch(获取分支更新) |
1 | 2.从远端仓库提取数据并尝试合并到当前分支:git merge(将更新合并到本地分支) |
也可以直接用’git pull origin master’实现远程拉取
3.6将本地仓库同步到git远程仓库踩过的坑:
大坑1:ssh模式未配置导致无法通过此方式沟通远程
1 | ERROR: Permission denied to deploy public key |
原因:经过查阅发现是ssh模式不支持 用户名+密码 验证,需要调整gitlab服务器ssh配置。
解决:
大坑2:ssh密钥部署出错
1 | ERROR: Permission to Biongd/Spider_douban.git denied to deploy key |
原因:我把ssh秘钥部署到单个项目(个人博客)的deploy中去了,打开个人窗口里的setting,可以看到there is no SSH keys associated with your account。
解决:进入单个仓库的setting-deploy,将ssh删除,然后点头像-setting-SSH and GPG keys,将本地ssh添加到这里
大坑3:本地版本和远程版本不同就push
1 | git push origin master |
原因:本地库和GitHub中的库不同步
解决:使用git pull —rebase origin master合并 GitHub 和 本地 的库,本地会多出之前不同步的文件。
大坑4:add远程端口时报错
$ git remote add origin git@gitee.com:biongd/notebook.git
fatal: remote origin already exists.
add origin相当于开了一个远端的端口,命名为origin,这个错误直接将origin删掉就可以了
解决:git rm remote origin
4.分支管理
4.1 如何新建和切换分支(HEAD)
可以将每一次的commit都看成是一次变化,并当成一次历史状态储存下来,也就是所谓的版本
git checkout -b dev
=git branch(新建分支)dev + git checkout dev
6-18更新:新的切换分支方式
git switch -c dev
此时dev和master指向同一个commit,HEAD切换到dev分支上,此时如果有新的commit,则HEAD和dev都指向新的commit,master仍在原来位置
4.2 合并和删除分支(切换到master下)
master:A-B-C
dev: A-B-C-D
git merge dev (master) 把dev分支的新commit merge到master上。
master:A-B-C-D
这是建立在dev分支比master超前一个版本的基础上
如果此时master也更新了一个版本,master:A-B-C-E
再次执行git merge dev
此时master分支多出一个新的合并后版本:A-B-C-E-F(F是把D和E合并的版本)
dev仍保持不变:A-B-C-D
删除分支:git branch -d dev
4.3 —rebase
master:D-E-F-G
在E版本处分出来一个分支dev,也进行了开发:D-E-A-B-C
这时候在master下,通过变基git rebase
即给topic换了一个爹master,此时的topic的路径就变成了
D-E-F-G-A‘-B’-C‘
和之前相比相当于引入了F-G两次提交的变化
4.4 origin/master
git pull 与 git fetch的区别
git pull:取回远程服务器(github)某个分支的更新,再与本地的指定分支合并。
即
git pull = git fetch + git merge
git fetch不会进行合并执行后需要手动执行git merge合并分支,而git pull拉取远程分之后直接与本地分支进行合并。更准确地说,git pull使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。
语法:
git pull origin master:brantest
和rebase类似,冒号右面的可以省略,可以知道是远程服务器向本地合并
知道了git pull的含义,-rebase模式也就更好理解了
即通过换爹的方式将远程分支并入本地
比如:
本地提交(master):A-B-C-D
push到远程(origin/mster):A-B-C-D
本地又回溯到C:A-B-C
远程:A-B-C-D
此时已经无法push,只能通过git pull —rebase将远程拉到本地,让本地也是A-B-C-D
本地再次提交E:A-B-C-E
远程:A-B-C-D
假设1:
假设D和E含共同文件且该文件内容不同,此时git pull —rebase也会产生冲突
解决方法:
1.强制覆盖:git push -u origin master -f
2.手动解决,然后continue
3.abort后,修改提交历史至相同分支。然后执行git pull或git push
假设2:
假设D和E含共同文件但相对C的修改并不一样,也就是没有冲突
我通过git pull —rebase origin master就能够给本地分支换个爹,
分支变为:A-B-C-D-E’
此时就可以push到远程,本地分支的基发生变化
总结
本地分支和远程分支就像是两个平行分支(虽然都叫master),区别只在于本地的merge操作换了种叫法
push就相当于远程分支下merge本地分支的内容
pull 就相当于本地分支下merge远程分支的内容
两台计算机和一个网络服务器就相当于三条平行分支了。。只是通过不断的pull和push来让3条分支齐头并进