==了解== 熟悉 掌握 精通
基本流程操作
初始化
git clone <http path>
直接凭空拉远程项目git init
在已存在的文件夹使用,生成一个仓库git remote add origin <SSH path>
连接到此path的远程仓库,本地须是仓库- 忽略. 新建的文件名是
.gitignore
- 符合正则,通配符那些。忽略文件夹就直接:
folder/
- 可以建多个
.gitignore
,它负责的范围就是它所在路径为根遍历的树。
- 符合正则,通配符那些。忽略文件夹就直接:
- 本地全局设定从master改成main,和github对应
- 两种方式改动:
- 在
.gitconfig
里添加[init] defaultBranch = main
- 用命令
git config --global init.defaultBranch main
- 在
- 但是已经生成的仓库还得手动改:
- 查看本地分支
git branch
- 如果不在master 则切到master
git checkout master
- 改
git branch -M main
- 查看本地分支
- 两种方式改动:
一周期流程
git clone 或者 git pull
## 上传
git add .
git commit -m '注释'
git push origin main
产生冲突了怎么办
pull的时候冲突了
- 不想要本地文件了
git clean -f # 删除本地同名文件
git pull # 拉取
- 强制覆盖本地文件
git fetch --all
git reset --hard origin/main
- 两地的更改都想保留
git add * # 将所有文件添加到git的跟踪列表中
git stash # 保存本地更改
git pull # 拉取
git stash pop # 合并
如果存在冲突,运行完pop之后文件就会标记冲突的地方,然后手动更改。然后再
从git add <刚刚的文件>
开始按流程push。
pull时错误:需指定合并方式
git push了报错有远程分歧,然后又git pull提示报错:
fatal: Need to specify how to reconcile divergent branches.
说明此时有冲突。
先git fetch
,下载下来,先不合并
然后可用git status
查看哪些文档修改了,哪些文档本地远程同时修改了产生冲突了。
此时该冲突文档一定有<<<<<<< HEAD
这种东西,然后手动修改。
修改好了之后就git add .
那一套push。
状态检查
查看本地和远程区别
git fetch
git diff origin/branchname
查看本地和远程的差异提交
git fetch
git log origin/branch_name..branch_name
查本地和远程分支的同步状态
git status
显示是否需要拉取(pull)远程更新,或推送(push)本地更改。
查远程仓库的详细信息
git remote show origin
显示哪些本地分支落后于远程分支,哪些需要推送。
git 配置文件
git 有三个配置文件
- system 系统
系统所有用户都会生效,一般在安装路径下
查看此文件路径:git config -e --system
我的在:/opt/homebrew/etc/gitconfig
- global 全局
当前用户生效
路径:$HOME/.gitconfig
- local 本地
仅当前项目生效
路径:(当前项目)/.git/config
优先级:local > global > system
设置用户名密码的时候使用的命令git config --global <用户名>
,global意思就是改在了global config里
多账户设置
添加额外的rsa公私钥
ssh -keygen -t rsa -C "email@work.com" -f "id_rsa_work_user"
全局设置
全局设置就是不用每次配置切换
在ssh config ~/.ssh/config
中添加多个账户
# Account 1
Host <nameA> # 本机域名 自己设 比如account1
HostName github.com # 固定,真正的域名或ip,网站地址
User git # 固定
IdentityFile ~/.ssh/id_rsa_account1
# Account 2
Host <nameB> # 本机域名 自己设 比如account2
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_account2
==!在使用的时候比如clone,所有git@github.com
的地方都换成 git@[HOST]
==,
例如:
git clone git@ccount1:username/repo.git
一个账户的时候都是git@github.com
,因为它默认的host是github.com
每次单独链接sshkey
可以不配置全局配置,每次切换操作:
ssh -add -D # remote 全部配置
ssh -add ~/.ssh/id_rsa_yours # 添加相应的key
如果要换已存在仓库的账户:
git remote rm origin # 如果之前已经和远程建立过链接,需要先清除当前连接
git remote add origin git@[HOST]:[github上的名字/仓库名字.git] # 重新建立连接
查看有没有连接好:
ssh -T git@[Host]
如果连接好了会返回:
Hi xxx!....
远程配置
查看本地对应的远程仓库:
git remote -v
如果不匹配,就重新设置
git remote set-url origin git@github.com-worker_user:worker_user/repo_name.git
新建仓库本地配置远程仓库
git remote add origin git@github.com-work_user:work_user/repo_name.git
ssh多账户、git多账户,ssh/http及切换流程
ssh多账户,是指可能有工作、个人等多个github远程账户,远程ssh连接的时候用,和提交作者无关,只用初始化的时候连接对应的HOST就可以了!
HOST在/.ssh/config
里HOST
设置。后续切换不用命令,只用进入对应的文件夹。
假设HOST
的名字是myhost
,github上本账户的名字是mygithub
(那么此项目地址应该是mygithub/project.git
), 注意clone的时候是git clone git@myhost:mygithub/project.git
就行了。
git多用户,是用来记录同一个/不同项目中提交作者的信息,和ssh连接无关。有系统、全局、本地三个设置,指的是/gitconfig
或.git/config
里的[user]
,设置name和email。可以和ssh的账户对应但根上无关。查看用:
# 设置
git config (--global) user.name
git config (--global) user.email
# 查看
git config --global --list # 全局
git config --list # 项目
http协议下,每次push都要输用户名密码like
Username for 'https://github.com':
让你输,但是!
这个不是输用户名的,而是在这个地方
输入这个token。没有就新建一个。
密码直接空。
不是很方便,所以需要 —— http切换为ssh协议:
# 查看当前远程 URL
git remote -v
# 更改远程 URL 为 SSH
git remote set-url origin git@github.com:username/repo.git
# 验证更改
git remote -v
# 测试 SSH 连接
ssh -T git@github.com
github协作模式
添加collaborator 比较直观就不记录了。
这里记录一个协作权限操作的问题。
clone别人项目
前置知识是clone,https url和ssh url的区别:
- HTTPS:不管是谁,拿到url随便clone,但是在push的时候需要验证用户名和密码;
- SSH:clone的项目你必须是拥有者或者管理员,而且需要在clone前添加SSH Key。
clone 别人项目方式
其实一般普通下载就可以了,此情况是想要提交代码,协作修改项目的情况。
- 加入协作者
具体方案是 项目拥有者or管理员添加你为collaborator,然后自己在邮件里同意。 - fork
- 把想clone的代码fork到自己的库,再clone
- 提交。本地改完之后先提交到自己的库,再点击
pull request
提交pull请求。
协作者clone 私有库方案
协作者clone public库试了一下没问题,但是当我作为collaborator 去clone仓库拥有者的库的时候,遇到了问题:public库正常,但private库报错:没有权限。
目前查到的结局办法是:用https的方式clone,并附token_。步骤如下:
- 设置token
路径:github.com → setting → personal access tokens → generate new token(现在有两个选项了 就选general就行) → 生成
勾选我就全勾选了因为当前要用的是我自己的项目 - clone项目
格式:git clone https://<生成的token>@<想下载项目的原路径>
这里<想下载项目的原路径>
即github.com/<repo_owner_name>/<repo_name>.git
简单概念
分区
git 分区名字必须记住,这个用的很多
- working dir,工作区,就是包括自己写代码的文件夹
- stage,暂存区,
- history,历史区
流程依次往后。
本地到暂存,用 add;暂存回本地,用checkout;
暂存到历史,用 commit;历史回暂存,用reset;
本地直接到历史,用 commit -a;历史回本地,用checkout 指定head;
历史的回退,实际上是将指针指向之前的head。
其它注意的点
当远程仓库与本地仓库不同时,如果强制push本地,是全部覆盖,而不是追加,远程有本地没有的文件,将会全部消失。
基础命令
追加提交:git commit --amend
分支
创建:git branch <name>
# 查看也是这个
切换:git switch <name>
# 本来是checkout 但这个名字太抽象了 我决定用新版命令
合并:git merge <othername>
# 这里是指将othername的分支,并到当前所在分支 主从关系这里有。要想哪个为主要先切到哪条。
合并系列顺序:创建并切到other分支 ➡️ 提交other ➡️ 切回主分支并提交 ➡️ merge other
复制式合并:git rebase <mainname>
# 这里是将当前分支归顺到目标分支上去,跟上面主从一样,但视角是反的。
复制系列顺序:创建并切到other分支 ➡️ 提交other ➡️ 切回主分支并提交 ➡️ 切回other ➡️ rebase main
一股脑复制:git cherry-pick <想挪的所有分支依次>
# 要按顺序。被挪的地方当前分支的下面
一股脑复制删除:git rebase -i HEAD~<x>
# -i是点开 可以编辑想要和不需要的节点
git rebase <A> <B>
相当于
git switch <B>
git rebase <A>
注意rebase 一参数的,相当于客人视角,给定主人地址,然后并过去
两参数是<主人地址> <客人地址>
的顺序。
此外,挪动是从它们的共同祖先开始的。
利用head挪动:
head目前感觉相当于当前指针,如果想将某个分支的当前指向停在任意节点,可以先将head指过去,再令当前分支指向head。
可以用hash值,也可以用相对路径。parent:^
,x代祖先:~x
^x:平级的第几个爸爸,~x:竖着的第几代祖先
git checkout HEAD~^2~3
:当前的爹的二号爹的爹的爹的爹
head挪过去:git checkout <hash值/HEAD ~x>
分支头再挪过去:git branch -f <分支名> HEAD~x
# -f 强制挪动
branch这个命令就是可以用来将一个指针挪到指定位置。
上面这两行也相当于
git branch -f <A> <B>
这两个参数 是被挪的指针 是目标节点
注意这里面的A B 都可以自由的加^``~
这些
想改之前的分支:
cherry-pick或者rebase
我个人觉得cherry-pick比较好理解,操作的都是本分支,命令中将想要的节点依次罗列就行了。想给哪个分支加点,就先switch到哪个下面就行。
branch 和 rebase都有一个git xxx <A> <B>
这样的命令,两个区别是branch是挪动指针,rebase是复制过来。
rebase还有一个点,如果A和B在一条线上,B落后,要用rebase A B,即将A新commit的部分复制给B。而不能用branch。
撤销提交
指的是commit之后的回撤。
本地撤销:git reset <当前分支的parent>
# 注意一定要加^, 是目标节点。比如main^
远程撤销:git revert <当前分支>
# 注意是本身,因为原理是开一个子节点和父节点一样,而不是直接回父。
标签
添加标签:git tag <分支名字> <标签名字>
标签是为了给版本打tag,只有重大更新完成之后可以使用这个。
# 打标签
git tag -a v1.0.0 -m "release 1.0"
# 查看标签
git tag --list
# 将标签同步给remote
git push --tags
远程
远程叫法:/ <远程仓库名>/<分支名>
意思是 本地存的,和远程进度一样的节点的指针。
如果fetch,是从指向o/main的节点算起
下载:
git fetch
git pull = git fetch + git merge
git pull origin foo
相当于:
git fetch origin foo; git merge o/foo
如果本地尚未明晰merge哪个,就先把远程fetch下来。
如果要检查远程和local的区别,必须先fetch:
git fetch # 先fetch
git diff origin/branch_name # 看本地和远程差异
git log origin/branch_name..branch_name # 看本地和远程分支之间的差异提交记录。
merge和rebase的区别是:merge显示合并的样子,rebase是直接挪的复制过来,变成一条线
git merge A,是将A合并至当前分支。主人视角。
推送:git push origin <localname>:<remotename>
这个命令暗含了远程追踪。如果俩名字一样,可以省略成一个名字。如果远程分支不存在,也可以用这个命令新创建。
空:
给远程推空可以删除分支:git push origin :<name>
# 删除远程name
给本地拉空可以新建分支:git fetch origin :<name>
# 新建本地name
系统配置 git config
查看:git config <内容>
,<内容> 可以是 --list
,也可以是具体参数。
增删:git config <范围> <动作> <参数 (值)>
范围是 --global
,--local
等,动作是--add
--unset
$ git config --local -–unset site.name
版本管理
概览:阮一峰:Git分支管理策略
进化:Arganzheng’s Blog:Git分支管理策略
实例:一个 Git 分支协作模式的进化故事
补充:唐玥璨:GIT分支管理办法