一、Git
仓库
仓库分为本地仓库和远程仓库,它们通过秘钥
和远程仓库地址
来建立连接。
A. 创建秘钥SSH KEY
(远程仓库:公钥,本地仓库:私钥)
$ ssh-keygen -t rsa -C "youremail@example.com"
- 若
Git
只管理GitHub
或GitLab
中的一个,直接用上述命令即可 - 执行命令后,会在
~/.ssh/
目录下生成私钥id-rsa
和公钥id-rsa.pub
。 - 若同时管理两个,则需为其指定一下名称。
$ ssh-keygen -t rsa -C "youremail@example.com" id_rsa_lab
$ ssh-keygen -t rsa -C "youremail@example.com" id_rsa_hub
B. 提示:若上述命令在普通cmd
界面执行,则可能会报错:
- 针对该问题,其实
git
相关命令都在git bash
中执行即可
- 或者自行添加环境变量:
1. 找到Git/usr/bin目录下的ssh-keygen.exe
2. 如果找不到,可以在计算机全局搜索
3. 属性-->高级系统设置-->环境变量-->系统变量,
找到Path变量,进行编辑,End到最后,输入分号,
粘贴复制的ssh-keygen所在的路径,保存;
重新cmd,执行ssh-keygen,成功!
- 若只想在
cmd
中临时使用,可以在Git/usr/bin
目录下直接执行ssh-keygen
的命令
C. 关于Git
同时管理gitHub
和gitLab
的问题
-
1) 之前看到的文章中是这么解决的
【但个人觉得不太好用,搞了大半天没搞定,果断放弃】
-
2)
ssh-add
相关知识点
① 添加私钥命令ssh-add id_rsa_lab
(原来的id_rsa
未执行相关命令,可用)
② 然后将对应公钥添加到对应服务端(这个很简单,就不列了),相应github
和gitlab
即都可用了
③ 如果在使用shh-add
的时候提示Could not open a connection to your authentication agent.
在git bash
中执行ssh-agent bash
④ 关于ssh-add
,这里有一篇文章貌似讲的比较详细,正确与否自行判断
上述链接的提问:我的
repo
分别推送到github
,gitcafe
。 正确添加了两个公钥私钥之后,并命名为id_github
和id_gitcafe
,发现每次push
代码 都必须重新ssh-add
上私钥。将id_github
名改回默认的id_rsa
,就可以直接push
了。但是gitcafe
被拒绝。有没有办法可以一次都设置上,不需要每次ssh-add
私钥的
3)
git remote add url
地址
① 本地新建工程(git init
),第一次push
前,需要先关联远程仓库
② 执行命令git remote add origin https://github.com.xxx.git
③ 命令行中的origin
可以改为其他的,类似别名吧
④ 第一次提交可使用-u
,执行git push -u origin dev
⑤-u
的作用:将会关联到远程的dev
(第一次指定哪个就是哪个)分支上,以后该工程就可以git push
不指定参数了4) 配置
user
相关信息:
即git log
显示的提交者信息;常用的配成global
,不常用的到相关git
工程下设置局部local
的即可。
所有的仓库都有效的配置方式:
git config --global user.name '您的名称'
git config --global user.email '您的Email'
只对当前仓库有效
git config --local user.name '您的名称'
git config --local user.email '您的Email'
二、 Git Bash
切换目录失败及修改默认启动路径
A. 目录有空格,切换目录失败,如Program Files
提示找不到目录:/d/Program
。进入d
盘查看,发现如果目录名中间有空格的时候,bash
默认是要加单引号的
注意,盘符前面要加上 / ,而且路径名是可以不区分大小写的,包括单引号里面的单词。
B. 每次打开bash
,进入的不是自己想要的工作空间,每次都要切换就有点费时间了,所以我们要修改默认加载目录。
具体步骤:
1、桌面找到Git Bash的快捷启动图标
2、把 –cd-to-home去掉
3、把起始位置中的“%HOMEDRIVE%%HOMEPATH%”替换成你的工作空间
4、重新打开bash,你就发现当前目录已经是你替换的目录了。
三、工作区与暂存区
如上图,将文件存入到Git版本库里,分两步执行:
① 用git add
命令将工作区的修改文件添加到暂存区;
commit
之前可以多次add
,
add file1, file2, file3;
add file4, file5;
已经add
的文件,又作了修改,如file3
,
别的不需重新add
,add file3;
即可
git add -A
: 把仓库内所有变更加入到暂存区
git add .
: 把当前目录及子目录下所有变更加入到暂存区
git add
后可以执行git status
:查看变更情况
② 用git commit
命令将暂存区的所有修改内容提交到当前分支;一旦事务提交之后,如果对工作区没有做什么修改,那么工作区就是干净的
四、Git命令
讲到工作区、暂存区、版本库,那这里就顺便了解下Git的相关命令吧
上面2步提到的命令 | file 表示某个文件 |
添加到暂存区 | git add xx |
查看变更情况 | git status |
提交 | git commit -m "xxx" |
多次commit后,如何查看历史版本呢 | log |
查看某个文件变更的所有commit | git log file |
显示就近的n个commit | git log -n |
一行显示commit(直接显示,信息很多) | git log --oneline |
用图显示所有分支的历史 | git log --oneline --graph --all |
某文件最后修改对应的commit | git blame file |
git diff: 比较 | -- |
比较某文件工作区和暂存区的差异 | git diff file |
比较某文件暂存区和HEAD的差异 | git diff --cached file |
比较某文件工作区和HEAD的差异 | git diff HEAD file |
比较工作区和暂存区的所有差异 | git diff |
比较暂存区和HEAD的所有差异 | git diff --cached |
比较任意两个commit的差异 | git difftool 提交A 提交B |
文件还原 | |
把工作区指定文件恢复成和暂存区一样 | git checkout file1 file2 |
把暂存区指定文件恢复成和HEAD一样 | git reset file1 file2 |
--- | --- |
把暂存区和工作区所有文件恢复成HEAD | git reset --hard |
Git中,HEAD表示当前版本,上个版本HEAD^,上上版本HEAD^^ |
100个版本写100个^太多,写成HEAD~100 |
把当前版本回退到上一个版本 | git reset --hard HEAD^ |
把当前版本回退到其他版本 | 可以按上面一次类推 |
回退到之前的版本后,原来较新的版本若没未推送到远端,则无法回到较新版本,除非知道commit-sha1 |
版本号无需写全,前几位就可,git会自动找。当然不能只写前一两位,找到太对,无法定位。 |
将工程切换成指定commit-sha1版本 | git reset --hard commit-sha1 |
我们还可以给commit-sha1(太冗长)打上标签tag |
不加commit-sha1的话默认当前版本 |
tag其他命令会在下方列出 | git tag 标签名 commit-sha1 |
--- | --- |
上面提到的checkout是恢复文件 | 下面checkout是切换分支 |
切换到指定分支 | git checkout 某个分支 |
创建分支并切换到该分支 | git checkout -b 新分支 |
基于checkout和恢复文件同命令,易误解 |
git2.23发布了 git switch来切换分支 |
创建并切换到新的dev分支 | git switch -c dev |
直接切换到已有的master分支 | git switch master |
讲到切换分支,下面讲下其他分支概念 | branch |
列出分支 |
|
查看当前工作在哪个分支 | git branch -v |
列出本地和远端分支 | git branch -av |
列出远端所有分支 | git branch -rv |
列出名称符合某样式的远端分支 | git branch -rv -l '某样式' |
新建分支 |
除了git checkout -b 新分支: |
基于当前分支创建新分支 | git branch 新分支 |
基于指定分支创建新分支 | git branch 新分支 已有分支 |
基于某个commit创建分支 | git branch 新分支 某个commit的id |
删除本地分支 |
|
安全删除本地某分支 | git branch -d 拟删除分支 |
强行删除本地某分支 | git branch -D 拟删除分支 |
删完本地分支,说下删除远端分支 | |
删除远端origin已不存在的所有本地分支 | git remote prune orign |
删除远端分支① | git push remote --delete 远端分支 |
删除远端分支② | git push remote :远端分支 |
删除已merge到master的所有本地分支:git branch --merged master | grep -v '^\*\ | master' | xargs -n 1 git branch -d
说到远端,了解下本地和远端的交互 | |
---|---|
当前工程对应的远端工程 |
remote |
列出所有remote | git remote -v |
增加remote | git remote add remote的名称 url地址 |
删除remote | git remote remove remote的名称 |
改变remote的名称 | git remote rename 旧名称 新名称 |
远端其他命令 |
|
把远端所有分支标签的变更都拉到本地 | git fetch remote名称 |
fetch + merge = pull | git pull remote名称 本地分支名 |
把本地分支push到远端 | git push remote名称 本地分支名 |
上面已经提过的删除远端分支 |
|
删除远端分支① | git push remote名称 --delete 远端分支 |
删除远端分支② | git push remote名称 :远端分支 |
从远程仓库克隆 |
git clone remote相关的url地址 |
标签tag相关命令 | |
---|---|
添加标签 | git tag -a version -m "注释" |
提交标签到远端 | git push origin -tags |
删除标签 | git tag -d version |
删除远程标签 | git push origin :refs/tags/version |
查看标签 |
git tag 或git tag -l
|
最后再附加个命令
查看哪些文件没被Git管控: git ls-files --others
五、分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
上面命令中已提到过了创建分支、切换分支啥的,这节主要讲讲分支的集成。
A. 分支合并:merge & rebase
① merge
|
|
---|---|
把A分支合到当前分支,并commit | git merge A分支 |
把A合到B,并commit | git merge A分支 B分支 |
git merge 和 git merge --no-ff的区别
通常,合并分支时,如果可能,
Git
会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward( --no-ff)
模式,Git
就会在merge
时生成一个新的commit
,这样,从分支历史上就可以看出分支信息
② rebase
|
|
---|---|
把当前分支基于B分支做rebase,以便把B分支合入到当前分支 | git rebase B分支 |
把A分支基于B分支做rebase,以便把B分支合入到A分支 | git rebase B分支 A分支 |
③ merge & rebase的区别是啥?,贴下知乎上比较简洁的答案
更多相关说法,点击上面链接,即可查看。
总之:尽量及时rebase上游分支,发现有冲突,merge
B. 分支策略:在实际开发中,我们应该按照几个基本原则进行分支管理
- 首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; - 那在哪干活呢?干活都在
dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本; - 你和你的小伙伴们每个人都在
dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
C. 分支合并冲突
- ① 分支
feature1
的readme.md
里写上Creating a new branch is quick & simple.
,提交 - ② 分支
master
的readme.md
里写上Creating a new branch is quick AND simple.
,提交 - ③ 将
feature1
合并到master
- ④ 手动解决冲突后再提交
- ⑤ 多人合作时的冲突呢(push冲突)? 先用git pull把最新的提交提交拉下来,然后,在本地合并,解决冲突,再推送
D. Bug分支【加塞临时任务的处理:stash
】
-
1.1
软件开发中,bug
就像家常便饭一样。每个bug
都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。 -
1.2
当你接到一个修复代号101
的bug
任务时,你可以创建一个分支issue-101
来修复它,但是,等等,当前正在dev
上进行的工作还没有提交: -
1.3
工作只进行到一半,无法提交,预计还需1天
时间。但必须在2h
内修复该bug
,咋办? -
Git提供了一个
stash
功能,可以把当前工作现场“储藏”起来。 -
2.1
执行命令git stash
然后你再通过命令git status
查看工作区,它是干净的。 -
2.2
bug
修复完成后,切换到dev
分支,并完成合并,最后删除issue-101
分支 -
2.3
把“储藏”的工作现场恢复,执行命令git stash pop
(pop = apply + drop
)
E. Feature分支【添加新功能】
- ① 软件开发中,总有无穷无尽的新的功能要不断添加进来
- ② 添加一个新功能时,你肯定不希望一些实验性质的代码,把主分支搞乱
- ③ 所以,一个新功能,最好建一个
feature
分支,在上面开发,完成后,合并,最后,删除该feature
分支 - ④ 合并前接到上级命令,由于某些原因,新功能必须取消!
- ⑤ 虽然白干了,但是这个包含机密资料的分支还是必须就地销毁
- ⑥ 执行命令
git branch -D
强行删除(-d
安全删除应该会提醒删除失败)
六、 Git
提交时的忽略文件
A. 哪些文件不能上传到git上?
① 类似Android Studio
自动生成的配置文件:不能上传到git
上,否则的话,如果你的同事下载下来,但是它的studio(gradle)
版本和你的不一样,或者其他配置的各种路径不一样,就需要重建项目,严重的话,根本无法重建项目,一片爆红!网上的方法也解决不了。
② 保存了数据库密码或者什么不能上传的文件......B. 忽略文件
.gitignore
的原则是:
① 忽略操作系统自动生成的文件,比如缩略图等;
② 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java
编译产生的.class
文件;
③ 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。C. 想知道忽略那些文件吗,很简单,找个大神的
github
,看看他的项目中怎么写的,就ok了!!!
/captures
# Built application files
*.apk
*.ap_
# Generated files
bin/
gen/
# Gradle files
.gradle/
/build
/*/build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Eclipse project files
.classpath
.project
.settings/
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
# System files
.DS_Store
七、GIT GUI
简单使用
注意:个人建议使用命令行方式进行版本管理,但是可以使用图形化界面看本次代码的改动,比较方便。
- 在所在项目,右键选择
git gui
- 界面如下,如果会使用命令行,那么一看就明白了
- 配置
UTF-8:Edit-Options
:
-
Add commit push
很快完成,不用输i
入命令
- 查看代码对比
如果想要查看所有的改动历史,可以:
就可以看到所有的代码改动历史,而不用去网上看。注意,这里能看到所有人的改动哦!!!非常强大!
- 设置和远程仓库关联(如果从项目根目录进入,则自动关联,不用设置) 如果需要设置,选择
remote-Add
,参考如下:
- 新建项目,从远程仓库克隆 。右键选择
git gui
:
选择克隆已有版本库: