# git-learn **Repository Path**: Mooooi/git-learn ## Basic Information - **Project Name**: git-learn - **Description**: 不会使用git只能度过相对失败的开发者一生 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-12-17 - **Last Updated**: 2025-01-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: Git ## README # 跟Wakaba酱一起学Git使用 ## 你需要知道的小知识 ### 什么是git? 版本管理系统主要分为两类: **集中式, 分散式**. **集中式**的特点是只有一个仓库供大家使用,所有的操作必须在与网络连接的条件下使用。 **分散式**的特点是开发者在自己的电脑上有各自的仓库,在适当的时刻同步到服务器上, 即使没网也能在自己的电脑看到历史记录 ### 为什么使用git? 信息透明,who, why, what, when的信息随手可得 ### **在哪里托管代码?** 在github/Bitbucket上可以创建远程仓库 进行github上的仓库主要分public/private两种类型,private通常会限制协助开发者数量最多为3人(不付费的情况). ### Git中常常见到origin 为什么使用这个词语? [(9 封私信 / 80 条消息) Git 里面的 origin 到底代表啥意思? - 知乎 (zhihu.com)](https://www.zhihu.com/question/27712995) 这个名字没有特别的意思,事实上完全可以使用阿猫阿狗进行替换。 和python中的self地位类似,大家约定俗成使用这个代表远端仓库默认名字 ### **为什么不使用master这个名字了?** 主要因为master有主人的意思,会给人不好的印象 所以2020年10月把master换成main作为默认分支的名字 ### 为什么commit强制写点什么? git会帮我们记录who what when, 但无法记录why, 养成写清楚注释的好习惯, 便于代码回滚 ### 分支是什么? > 官方解释: 指向提交对象的可变指针 ### 忽略无需进行版本管理的文件 在git中,有些文件或目录并不一定需要进行版本管理,例如 * 系统自动生成的文件 * 缓存 * 容量过大的文件 这时可以使用`.gitignore`对上述文件进行指定,下面介绍书写规则: ``` memo.txt # 忽略自己用的备忘录文件 *.rbc # 忽略拓展名为rbc的文件 !test.rbc # 作为例外情况,不忽略rbc template_c/ # 忽略template_c以下的所有文件 /log/ # 忽略根目录的log子目录下的所有文件 用#表示注释 ``` ### 分支的使用规则 * master分支,内容比较稳定,原则上不在master分支发布,而是在topic分支进行操作 * topic分支, 增加新功能和升级设计,从master分支上新建分支。名称最好简单易懂,反应你的工作内容 ### 这两个地址有啥区别 **1. 访问方式** - **SSH 协议 (`git@...`)**: - 使用 SSH 密钥进行身份验证。 - 需要事先配置 SSH 密钥对,并将公钥添加到 Gitee 账户中。 - 配置完成后,使用方便,无需每次输入用户名和密码。 - **HTTPS 协议 (`https://...`)**: - 使用用户名和密码进行身份验证。 - 或者使用 **Personal Access Token(个人访问令牌)** 代替密码。 - 每次操作时可能需要输入认证信息(除非启用了凭据管理工具)。 - **2. 适用场景** - **SSH 更适合长期使用**: - 对于频繁访问的开发者,SSH 是更方便和安全的选择。 - 配置完成后,无需每次输入认证信息。 - **HTTPS 更适合临时访问或网络限制环境**: - 如果无法配置 SSH,HTTPS 是一个直接的替代选项。 - 适合需要通过代理访问的场景(部分代理可能限制 SSH 流量,也是为啥github下载项目没问题,但是clone pull push经常翻车的原因) ![image-20241219204615774](./assets/image-20241219204615774.png) ### SSH密钥到底是个啥 用于身份验证,如果用https,每次提交到远端都要输入账号密码,比较麻烦,SSH实际做了身份验证工作,这样不用每次都输入密码了。 SSH 密钥在代码托管平台上针对**用户账户**的,而不是单独绑定某个特定仓库。 生成的 SSH 密钥是与 **具体的计算机** 绑定的,而不是直接跟随用户。 #### SSH 密钥绑定的原理 1. **SSH 密钥的本地存储**: - SSH 密钥对由一个私钥(`id_rsa`)和一个公钥(`id_rsa.pub`)组成,存储在生成时指定的计算机本地路径(默认是 `~/.ssh/` 目录)。 - 私钥绝对不能泄露,公钥可上传到服务器(如 Gitee)用于认证。 2. **计算机与密钥绑定**: - 每台计算机生成的 SSH 密钥对是唯一的,私钥文件只存在于生成密钥的那台计算机上。 - 因此,只有拥有该私钥的计算机能够通过 SSH 与服务器通信。 3. **用户身份验证依赖于密钥的配对**: - 当你将公钥上传到 Gitee 后,Gitee 会将其与你的账户绑定。 - 只有存有对应私钥的计算机才能访问与你账户关联的仓库。 #### 用户和计算机的关系 - **密钥跟随计算机**: 如果你换了计算机,即使登录相同的账户,也无法使用旧计算机的密钥,必须在新计算机上生成新的密钥并上传到 Gitee。 - **用户可以管理多台计算机的密钥**: Gitee 等平台允许为同一账户添加多个 SSH 公钥。 你可以为每台计算机生成一对密钥,并将它们的公钥都上传到 Gitee。 ------ #### 场景分析 #### 情况 1:多台计算机 如果你需要在多台计算机上访问同一个仓库: - 在每台计算机上分别生成一对 SSH 密钥。 - 将每台计算机的公钥都上传到 Gitee 账户中。 #### 情况 2:重新安装系统或换设备 如果你更换了电脑或重新安装了系统: - 原来的私钥文件会丢失,导致无法再通过 SSH 访问 Gitee。 - 需要在新环境下重新生成密钥并上传公钥到 Gitee。 ### SSH配置 #### 密钥生成 这里推荐使用git bash命令行进行配置 -C后面输入你对密钥的注释 ``` ssh-keygen -t ed25519 -C "your_comment" ``` 连续按下3次回车,查看.ssh内密钥 ``` ls ~/.ssh/ # 预期输出 id_ed25519 id_ed25519.pub ``` 查看公钥,并复制公钥到远端 ``` cat ~/.ssh/id_ed25519.pub ``` ![image-20241226115359098](assets/image-20241226115359098.png) ``` # 配置正确会显示用户名并欢迎 ssh -T git@gitee.com ``` #### SourceTree 密钥选择OpenSSH ![image-20241226115620011](assets/image-20241226115620011.png) ## Github 我们通常将代码上传的地方. 在这里fork别人的代码,准确含义是复制他人公开的远程仓库到自己的账号 ![image-20241217191540671](assets/image-20241217191540671.png) ## Gitee 与现实妥协了,github经常连不上,特别是pull和push非常滴高血压. gitee最大的好处是连接非常稳定,再也不需要magic🧙‍♀️了, 还是中文平台!(虽说广子有点多) ![image-20241217212501662](assets/image-20241217212501662.png) ## SourceTree 官网搜索即可免费下载[Sourcetree | Free Git GUI for Mac and Windows](https://www.sourcetreeapp.com/) 图形化界面 非常简单易懂 ### **添加仓库和创建仓库** 注意这里是添加仓库,仓库需要有git文件进行管理... > 如果之前用的GitBash进行代码管理,又添加了一些新文件,SourceTree会无法add这些文件, 原因解释[SourceTree识别不了新添加的文件夹 ](https://blog.csdn.net/qq_37478078/article/details/89381809?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~PaidSort-1-89381809-blog-87818783.235^v43^pc_blog_bottom_relevance_base5&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~PaidSort-1-89381809-blog-87818783.235^v43^pc_blog_bottom_relevance_base5&utm_relevant_index=1) 如果你的项目处于新建文件夹阶段,请选择add右边的Create, 哪怕你拥有一定的代码,但没有git文件,也不能称之为一个仓库,所以还是需要选择`创建仓库`. 管理代码时,为避免奇怪的bug, 请只使用一套git管理工具, 不要混用! ![image-20241217193528787](assets/image-20241217193528787.png) branch显示 ![image-20241217121001906](assets/image-20241217121001906.png) ### 删除分支 > 不要选择删除origin!!! 这会把远端仓库直接删掉!!! 分支界面,右键点击即可删除分支。删本地的在本地分支删除,删远端的在远端分支删除~ 删除分支,已经合并过的提交并不会消失。 其他成员删除的远程分支,在本地也想删除,勾选“删掉所有远端现已不存在的跟踪分支”: ![image-20241219101047906](assets/image-20241219101047906.png) ### 给提交做标记 使用标签可以给提交历史中的重要节点加上标记,便于以后的查找。 ![image-20241219104250639](assets/image-20241219104250639.png) 类似操作,可以删除标签 ![image-20241219104430514](assets/image-20241219104430514.png) ### 错误地把HEAD直接指向某次提交 这是`detached HEAD`状态。它不属于任何分支的无所属状态(分离头指针状态),此时也可以继续进行提交,但下次checkout后,回不到现在的状态,因为没有任何标记 Solution: 把当前所指向的提交放到一个新分支即可,解除这一状态。 在detached head状态不要进行提交。 如果不小心进行了提交,我们可以创建新分支保存这次提交 ### 重要快捷键整理 ``` f5: 刷新页面 alt+shift+c: 提交代码 cttl+shift+p: push到远端 ctrl+shift+l: pull远端到本地 ``` ### amend 此方法在推送前使用。 如果我们发现最新的提交中注释不小心写错字了,在提交选项中选择“修改最后一次提交” ![image-20241219101821181](assets/image-20241219101821181.png) 这样可以允许我们修改错别字. ### checkout 执行这个命令,让操作目录的文件变成指定时刻的文件。 即使已经checkout到过去的提交,还是可以回到最新的提交 ![image-20241217185400203](assets/image-20241217185400203.png) 每次提交都会分配由字母和数字组成的字符串commit id, 这是根据内容生成的哈希值(确保每次提交的唯一性) 我们当然也可以checkout到过去的提交,然后在对应的位置创建一个新分支。 ### clone 把远程仓库下载到本地. ### merge 合并分支。 使用场景: 发布分支: main 开发者拉取debug分支修复bug,修好了再merge到main分支 例子: ``` print("Hello World from main branch") # main branch print("Hello World from dev branch") # dev branch ``` ![cc98b3dfc5f9e2dc1ce67d92443a0c87](assets/cc98b3dfc5f9e2dc1ce67d92443a0c87.png) 合并过程:在master分支上,右键点击想要合并的分支,点击合并`dev`至当前的分支。 ### fetch 想知道远程仓库的最新状态,但还不想同步到本地仓库时使用。 SourceTree中选择“获取”,即可获取最新的远端更新,但此时还没有更新到本地分支 ![image-20241219095857246](assets/image-20241219095857246.png) 接下来,在本地的main分选中远端最新推送,点击“合并” ![image-20241219100101331](assets/image-20241219100101331.png) ### push 提交我们的代码,点击推送,设置好我们的仓库地址即可~ ### pull | branch | 说明 | | ------------ | ------------------------------------------------ | | 远程分支 | 存在于远程仓库 | | 远程跟踪分支 | 存在于本地仓库,是远程分支在本地的镜像,只可读取 | | 本地分支 | 存在于本地仓库,一般进行提交的分支 | pull = fetch + merge pull的本质是先把远程分支的最新更新fetch到本地的远程跟踪分支,再将远程跟踪分支merge到本地分支。 ### conflict 同一行代码,同一时间被不同的人修改 自己选择正确的代码 ### revert revert: 恢复 让一次提交反向适用。 不是直接删除过去的某次提交,而完全使用与过去某次提交相反的内容来进行一次新的提交,从而覆盖过去的变更。 例子 我已经在测试.txt写入内容: 床前明月光,疑是地上霜。 并进行了一次提交,但我在新的一次提交中不小心删除了“明月”两个字: 床前光,疑是地上霜。 这时,可以使用回滚操作 ![image-20241218204538245](assets/image-20241218204538245.png) 这样就能撤销我们的误操作,如果出现conflict则需要我们手动选择需要的代码. ### rebase 提交历史合并为一条直线(变基) Merge时,提交历史保持原来的分流状态,而rebase时,提交的历史合并为同一条直线。 因为大家同步修改代码,master分支一直在迭代,后面如果有许多conflict就会非常麻烦,所以最好尽快读取master分支上的新迭代。 ![e9bc58666bd72411c48d6274399bec9f_720](../../QQFiles/Tencent Files/1940847447/nt_qq/nt_data/Pic/2024-12/Thumb/e9bc58666bd72411c48d6274399bec9f_720.jpg) rebase = re + base, 想象为把分支连根拔起,重新栽种。 无论是merge还是rebase,合并后的源代码都是一样的,只是生成的提交历史的形状不同。 但是`rebase`会**改变提交的历史,所以有一定的风险**。 ### squash 合并多个提交。 修改了多次,结果提交历史变得冗长,如果能把多个提交合并为一个,提交历史会更加整洁。 **如果提交已经在远程仓库存在**,此时改变提交,会导致远程仓库和其他开发者的本地仓库存在差异,引发混乱。 所以确认,要合并的多个提交**只存在于自己的本地仓库**。 很容易点错,要按顺序来: 选择没提交的一串分支前的一个提交,右键点击交互式变基的子提交。 不要对已经在远程仓库存在的提交进行交互式变基,例如这里就应该对“举头望明月,低头思故乡”提交进行操作。 ![a33de222ade0ed9711197db60c4114fd](assets/a33de222ade0ed9711197db60c4114fd.png) 选中想要进行的提交,点击“用此前的squash”按钮,可以编辑信息,修改一下整合版本的注释,最后再点击确定。(**不要直接点确定**) 如果你觉得自己绕晕了,可以点“重置”,重新操作一次. ![2f2d1d436c6958b6017a9046c0556d77](assets/2f2d1d436c6958b6017a9046c0556d77.png) **这个操作会改变提交历史,所以存在一定的风险性。** ### stash stash: 隐藏;存放;贮藏. 该命令允许我们把正在操作的目录暂存在某个地方,其变更内容可以稍后恢复 暂存未提交的内容. 1. 进行到中途的任务,通过stash进行暂存 2. 完成插入任务后,再恢复进行之前的工作内容 否则未暂存的内容无法被正确记录,此时直接移动会丢失我们本次未提交期间所做的更改 暂存后,SourceTree的“未提交的更改”消失,可以安全移动到其他分支 选择“储藏”,并设置一条信息: ![image-20241219102657753](assets/image-20241219102657753.png) 工作完成后,点击应用即可恢复之前做一半的工作 ![image-20241219102746525](assets/image-20241219102746525.png) ### cherry-pick 场景:a提交想提交到A branch上,但不小心选择提交到B branch上,此时可以用cherry-pick解决这个问题 把指定的提交复制到当前分支上,而不是移动提交,此时原提交还存在于原分支上。 此时不想要的提交还在原分支,我们可以使用revert回滚命令 在你想要正确提交的分支上,选择你错误的那次提交,点击“遴选”,解决冲突后,即可提交代码到目标分支. 回到错误分支,选中提交,点击“回滚提交”,即可撤销. ![image-20241219103911753](assets/image-20241219103911753.png) ### .gitignore SourceTree在设置处可以编辑.gitignore文件 ![image-20241218200158378](assets/image-20241218200158378.png) 有时,我们想要忽略`已经提交的文件`, 可在文件状态窗口选择你想要停止跟踪的文件,当然记得写好commit,避免忘了为啥不再跟踪这个文件 **最后记得把这个文件添加到.gitignore文件**!!! ![image-20241218200518489](assets/image-20241218200518489.png) ## 命令行交互 ``` git add README.md # 把文件添加到暂存区 可传入目录/文件 # git add . # 传入所有文件 ``` git的运行结构 ![img](https://www.runoob.com/wp-content/uploads/2015/02/git-command.jpg) ### git的创建 ``` git init # 创建该文件夹为一个git仓库 git commit -m "这是提交信息" # Windows用的是双引号 linux用的单引号 # commit 最好不要传空的 git commit # 进入vim 可以写的更多 ``` ### 正确的提交过程 ``` git init //初始化仓库 git add .(文件name) //添加文件到本地 git commit -m “first commit” //添加文件描述信息 git remote add origin 远程仓库地址 //链接远程仓库 git remote set-url origin xxxxx.git //修改远程仓库地址 git pull origin main // 把本地仓库的变化连接到远程仓库main分支 git push -u origin main //把本地仓库的文件推送到远程仓库main分支 ``` ==.gitignore==: 比如忽略a/b下的子文件 应写入:**a/b/**,而不是a/b ### 一些重要的命令 ``` git branch # 查看本地分, *号标记当前所在分支 git branch -d (branchName) # 删除分支 git branch -m master main # 把名为master的分支改为main(只修改了名字) git remote -v # 查询远端仓库的地址 git status # 查询文件状态 # 删除已经add的文件 git rm --cached "文件路径" # 只删除缓存,不会物理删除文件 git rm --f "文件路径" # 物理上也把文件删除了 ``` ### 常见bug修复 `典中典之我为啥push不了?我也尝试pull了,但失败了...` 出现这个bug最大的可能是,工作流紊乱,例如 > 你在本地已经创建了仓库A, 并初步完成了项目;与此同时,你在github创建了一个远端仓库A*,并初始化,生成了license, README, gitignore等文件。此时尝试把本地代码推送到远端会提示失败(unrelated history) 这个bug的原因是,我们主观认为这两个仓库是一个仓库,但事实上这两个仓库在逻辑上是独立的,哪怕它们的名字相同。解决这个bug的思路是,调整我们的工作流,一种解决方案是:本地先创建git repo,完成初步开发后,远端仓库只进行初始化,不生成README文件,这样不会出现conflict,从而顺利上传。另一种方案是:一开始就在远端创建一个仓库,我们在本地clone这个空仓库,从根源上避免合并失败,之后我们不断进行开发,将代码提交到远端(推荐)。 注意检查自己所在的分支是不是搞混main和master 可能会有超出预期的错误 提交时,注意不要让自己的版本落后于远端版本 所以需要先pull远端修改再push你的修改内容 **连接超时!**(github经常出现这个问题, 国内使用gitee99.9%不会出现) 在git bash输入 ``` git config --global --unset http.proxy git config --global --unset https.proxy ``` 参考: [完美解决 git 报错 “fatal: unable to access ‘https://github.com/.../.git‘: Recv failure Connection was rese-CSDN博客](https://blog.csdn.net/qq_43546721/article/details/139506583)