Git 使用笔记

参考链接:

创建版本库 - Git教程 - 廖雪峰的官方网站

Git使用教程,最详细,最傻瓜,最浅显,真正手把手教 - 知乎

可视化教程链接:

Git可视化极简易教程 — Git GUI使用方法 | 菜鸟教程

沙盒教程链接:

Learn Git Branching

PyCharm中将项目推送到GitHub:PyCharm 使用 Pycharm 和两步验证将项目推送到GitHub|极客教程

拉取新项目到本地

  1. 复制http的网址,
  2. 文件夹打开git base黑框,输入git clone http....拉取
  3. 拉完后进入对应文件夹打开git base黑框,输入“code .”,注意是空格+小数点。(即可再vscode上将项目打开)

over

初创仓库

  • 在项目根目录打开 PowerShell:
    git status
  • 如果还不是 Git 仓库:
    git init
    git add .
    git commit -m "项目初始版本"
    git branch -M main
  • 如果已经是 Git 仓库,建议先把当前稳定版本提交:
    git add .
    git commit -m "并行开发前的稳定基线"

命令使用

如果你不需要全面的手册,只需要可用选项的快速参考,

那么可以用 -h 选项获得更简明的 “help” 输出:例如 git add -h

cd f:        切换目录到 F 盘

cd gitCxl        切换目录到 gitCxl 文件夹

mkdir gitCxl        创建新文件夹 gitCxl

pwd        打印当前目录


  • ———— 【新建代码库】

git init        将当前目录设置为git可管理的仓库(在当前目录新建一个Git代码库)

git add readme.txt        将 readme.txt 添加到暂存区

git add [file1] [file2] ...         添加指定目录到暂存区,包括子目录
git add [dir]        添加当前目录的所有文件到暂存区

git add --all        将当前目录下的所有文件和文件夹添加到暂存区

git add -u        添加所有已修改的文件(添加所有已修改的文件添加到暂存区中。这包括已经被 Git 跟踪的文件,并且在工作目录中已经被修改的文件)

git add -A        添加所有已删除的文件(添加所有已删除的文件添加到暂存区中。这包括已经被 Git 跟踪的文件,并且在工作目录中已经被删除的文件)

git add .        将当前目录下的所有变更增加到暂存区(添加所有未跟踪的文件)

git commit -m "提交说明"        把暂存区内的所有文件提交到仓库

git commit --amend -m "新的提交注释"        修改最近一次提交的注释

git reset --soft HEAD~1        完全撤销上一次提交(但保留代码更改),(撤销后可重新提交并修改注释)

常用的 git commit 参数和选项:

常用的 git commit 参数和选项:
-m <message> 或 --message=<message>
    直接在命令行上指定提交信息(commit message)。这是最常用的参数之一,因为它允许你快速附加一条描述性消息来解释更改。
-a 或 --all
    自动将所有已跟踪文件的更改(包括那些没有被 git add 明确添加到暂存区的文件)提交。这通常用于快速提交所有更改,但请注意,它不会添加新文件到仓库中。
-v 或 --verbose
    在提交时显示差异(diff)和提交信息。这有助于在提交前再次确认更改。
--amend
    修改最近的提交。这允许你更改最近的提交信息或添加更多更改到该提交中,而不是创建一个新的提交。
--signoff 或 -s
    在提交信息中添加一个签名行(Signed-off-by),这通常用于表示你同意某些开发准则或协议。
--no-verify
    绕过提交前的钩子(hook)脚本。Git 允许你在提交前运行自定义脚本以检查代码风格、测试等。使用此选项可以跳过这些检查。
--allow-empty
    允许创建一个空的提交(即没有更改的提交)。这通常用于记录项目状态或触发某些构建/部署流程。
--allow-empty-message
    允许提交一个空的提交信息(即不附带任何描述)。通常,Git 会阻止这种提交以防止无意义的提交记录。
--template=<file>
    使用指定的文件作为提交信息的模板。这可以帮助你遵循特定的提交信息格式或包含额外的信息。
--author=<author>
    指定提交的作者信息。这通常用于修复错误的作者信息或代表其他人提交更改。
--date=<date>
    指定提交的日期和时间。这可以用于调整提交的时间戳,但通常不建议这样做,因为它可能会混淆项目的历史记录。

git config --list        显示当前的Git配置

git status        查看是否还有文件未提交(工作区状态)

git diff readme.txt        查看readme.txt文件内的改动

查看工作区和暂存区之间的差异 git diff

# 查看工作区和暂存区之间所有文件的差异
git diff

# 查看具体某个文件在工作区和暂存区之间的差异
git diff -- 文件名

# 查看多个文件在工作区和暂存区之间的差异
git diff -- 文件名1 文件名2 文件名3

查看工作区和版本库之间的差异 git diff HEAD

# 查看工作区与最新版本库之间的所有文件差异
git diff HEAD

# 查看工作区与具体某个提交版本之间的所有文件差异
git diff 具体某个版本

# 查看工作区与最新版本库之间的指定文件差异
git diff HEAD -- 文件名

# 查看工作区与具体某个版本之间的指定文件差异
git diff 具体某个版本 -- 文件名

查看暂存区和版本库之间的差异 git diff --cached

git diff HEAD HousePrices.py        比较HP.py文件 工作区版本 与 仓库最新版本 间的差异

# 查看暂存区和上一次提交的最新版本 (HEAD) 之间的所有文件差异
git diff --cached

# 查看暂存区和指定版本之间的所有文件差异
git diff --cached 版本号

# 查看暂存区和 HEAD 之间的指定文件差异
git diff --cached -- 文件名

# 查看暂存区和指定版本之间的指定文件差异
git diff --cached 版本号 -- 文件名

查看不同版本之间的差异 git diff 版本号1 版本号2

# 查看两个版本之间的差异
git diff 版本号1 版本号2

# 查看两个版本之间的指定文件之间的差异
git diff 版本号1 版本号2 -- 文件名

# 查看两个版本之间的改动的文件列表
git diff 版本号1 版本号2 --stat

# 查看两个版本之间的文件夹 src 的差异
git diff 版本号1 版本号2 src

git log        查看从近到远的提交日志(历史记录)

git log --pretty=oneline        只查看提交说的注释信息

————

回退到上一个版本:git reset --hard HEAD^

回退到上上个版本:git reset --hard HEAD^^

回退到前100个版本:git reset --hard HEAD~100

注:

--hard会回退到上个版本的已提交状态,

--soft会回退到上个版本的未提交状态,

--mixed会回退到上个版本已添加但未提交的状态。

git reflog        可获取版本号

git reset --hard 版本号        回退到版本号对应的那个版本

————

git ls-tree -r HEAD        显示当前分支下所有文件和文件夹的信息,递归到子树

git ls-tree HEAD        显示当前分支下所有文件和文件夹的信息(包括文件的类型、属主、对象(blob或tree)的SHA-1哈希值等)

git ls-files        显示当前分支下所有文件的相对路径

cat readme.txt        查看readme.txt的内容(实验发现是本地文件的内容,不是仓库中文件的内容)

git reflog        获取版本号;

git reset --hard 版本号        回退到版本号对应的那个版本

git diff HEAD -- readme.txt        查看工作区和版本库里面最新版本的区别

git checkout -- readme.txt        丢弃工作区的修改,把readme.txt文件在工作区做的修改全部撤销,有两种情况:(其实就是检出)(也可以把checkout换成resrore)

  1. 若自修改后未放到暂存区,则回退到版本库的状态;
  2. 若修改后已经放入暂存区,则回退到添加暂存区后的状态。
  • 注意:命令git checkout -- readme.txt 中的 -- 很重要,若没有 -- 的话,则命令变成创建分支(切换到另一个分支)。

git reset HEAD <file>        把暂存区的修改撤销掉(unstage),重新放回工作区

git restore <file>        丢弃工作区的更改

git restore --staged <file>        撤销暂存区提交(只会删除暂存区的文件,不会影响工作目录)

rm b.txt        删除工作区的b.txt文件

git rm b.txt        从版本库中删除 b.txt 文件(删除后记得 git commit 提交)

git rm -r --cached 要删除的文件或文件夹绝对路径        把某目录/文件从 Git 的追踪中移除(stop tracking),但在工作区保留文件,并用 .gitignore维持后续不再进入追踪

例如:

  • git rm -r --cached E:/projec/振镜拼接/ImageProcessing/.vs
  • git rm -r --cached E:/projec/振镜拼接/ImageProcessing/ImageProcessing/x64

  • ———— 【添加/删除远程库 & 从远程库克隆】

ssh-keygen -t rsa -C "youremail@example.com"        创建SSH Key

git remote add origin https://github.com/chxin14160/gitCxl.git        在本地的 gitCxl 仓库下运行,关联GitHub仓库

  1. git remote add github git@github.com:michaelliao/learngit.git
  2. git remote add gitee git@gitee.com:liaoxuefeng/learngit.git

git push -u origin master        初次提交,把本地master分支的最新修改推送到github上

git push origin master        把本地master分支的最新修改推送到github上

git remote -v        查看远程库信息

git remote rm origin        删除远程库 origin(解除了本地和远程的绑定关系)

git clone https://github.com/chxin14160/gitCxl2        从GitHub的对应地址中克隆一个本地库(普通克隆方式,默认克隆默认那个分支,且只有默认那个分支)

git clone -b master https://github.com/chxin14160/gitCxl.git        克隆远程仓库地址https://github.com/chxin14160/gitCxl中的master分支(克隆远程指定分支)

git branch dev origin/dev        新建一个本地分支来跟踪远程的某一分支,创建该分支后,远程分支内容已拉取到本地分支(要先进入仓库目录,再执行该命令)

git pull github master        将远程的更改拉取到本地并自动合并

检查远程分支状态:

git fetch github        获取远程最新信息

git log github/master        查看远程提交历史

git log master        查看本地提交历史

git remote set-url origin http://xxx(新地址)        将绑定的远程仓库修改为新地址


  • ———— 【分支管理】

git branch dev        创建分支

git checkout dev        切换分支dev(或者 git switch name)

git checkout -b dev        创建并切换分支dev(或者 git switch -c name)

(git checkout -b dev 相当于 git branch dev 创建分支dev + git checkout dev 切换分支dev

git branch        查看当前分支,会列出所有本地分支,当前分支前面会添加一个星号 “*”

git branch -r        列出所有远程分支

git branch -a        列出所有本地分支和远程分支

git merge dev        在master上运行,把dev的内容和合并到当前分支master上(合并指定分支到当前分支)

git merge --no-ff -m "merge with no-ff" dev        合并,但是禁用 fast forward 模式

git branch –d dev        删除分支dev

也就是:

  • 切换分支:git checkout name 或者 git switch name
  • 创建+切换分支:git checkout –b name 或者 git switch -c name

git stash        将当前工作现场隐藏起来 (可多次使用)(将本地没提交的内容(git commit的内容不会被缓存 但git add的内容会被缓存)进行缓存并从当前分支移除,缓存的数据结构为堆栈,先进后出)

git stash list        查看stash了哪些存储,每一行的冒号前面的字符串就是标识此隐藏的id

git stash apply        恢复stash的内容(默认为第一个)

git stash apply stash@{1}        恢复第二个stash的内容(因为下标从0开始)

git stash drop        删除stash的内容(默认为第一个)

git stash pop        恢复的同时把stash内容也删除(默认为第一个stash,即stash@{0}。)

(将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下)

如果要应用并删除其他stash,命令:

git stash pop stash@{1}         应用并删除第二个stash的内容

git cherry-pick d890941        把提交编号为d890941所做的修改 全部复制到当前所在分支

git clean        删除未提交的修改

git branch -D feature-tmp        强行删除feature-tmp分支


远程库的默认名称是origin

git remote        查看远程库的信息
git remote –v        查看远程库的详细信息

git push origin master        将本地的master分支推送到远程库对应的远程分支上

git push origin dev        将本地的dev分支推送到远程库对应的远程分支上

git checkout –b dev origin/dev        创建本地dev分支

git pull        把最新的提交从远程库origin/dev抓取下来

git branch --set-upstream-to=origin/dev dev        指定本地dev分支与远程origin/dev分支的链接

git branch --set-upstream branch-name origin/branch-name        同上,建立本地分支和远程分支的关联


  • ———— 【标签管理】

git tag v1.0        (创建标签)给当前分支打上标签为v1.0

git tag        查看所有标签

git log --pretty=oneline --abbrev-commit        查找历史提交的commit id

git tag v0.9 0f3d70b        给commit id为0f3d70b的这次commit打上标签为v0.9

git show v0.9        查看标签为v0.9的commit信息

git tag -a v0.6 -m "添加a文件" 06b9341        (创建带有说明的标签)给commit id为06b9341的这次commit打上标签为v0.6,注释详细为"添加a文件"

git tag -d v0.5        删除本地标签v0.5

git push origin v1.0        将标签v1.0推送到远程库

git push origin --tags        一次性推送全部尚未推送到远程的本地标签到远程

(要删除已推送到远程的远程标签,需先从本地删除,然后再从远程删除)

git push origin :refs/tags/v0.9        (删除远程标签)从名为origin的远程仓库中删除名为v0.9的标签

👉初始创建版本库

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

因为Git是分布式版本控制系统,所以需要填写用户名和邮箱作为一个标识。

注意:git config --global 参数,有了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然你也可以对某个仓库指定的不同的用户名和邮箱。

cd 是 "change directory" 的缩写,意为“切换目录”;

mkdir 是 "make directory" 的缩写,用于创建新目录(文件夹)

pwd 是 "print working directory" 的缩写,意为“打印当前工作目录”,用于显示当前的目录

git init 把当前的这个目录变成 git可以管理的仓库

git add readme.txt 版本库gitCxl目录下记事本文件 readme.txt添加到暂存区里面去(没有任何提示,则说明已经添加成功)。

git commit 告诉Git,把文件提交到仓库 (-m后" "里的内容为本次提交的注释说明)。

git commit命令执行成功后会告诉你:

  • 1 file changed:1个文件被改动(我们新添加的readme.txt文件);
  • 2 insertions:插入了两行内容(readme.txt有两行内容)。

git status查看是否还有文件未提交

  • 黄色:说明没有任何文件未提交;
  • 蓝色:告诉我们 readme.txt 文件已被修改,但是未被提交的修改。

git diff readme.txt 查看readme.txt文件到底改了什么内容,如下:

如上可看到,readme.txt文件内容从二行改成 三行 添加了一行22222222内容。

知道了对readme.txt文件做了什么修改后,我们可以放心的提交到仓库了,提交修改和提交文件一样的2步(第一步是git add 第二步是:git commit)

输入git add readme.txt

报错1:fatal: not a git repository (or any of the parent directories)

原因:Git命令必须在Git仓库目录内执行(git init除外),在仓库目录外执行是没有意义的。

报错2:fatal: pathspec 'readme.txt' did not match any files

原因:添加某个文件时,该文件必须在当前目录下存在,用ls或者dir命令查看当前目录的文件,看看文件是否存在,或者是否写错了文件名。

  • 总结:

初始化一个Git仓库,使用git init命令。

添加文件到Git仓库,分两步:

  1. 使用命令git add <file>,(可反复多次使用,添加多个文件);
  2. 使用命令git commit -m <message>,完成。

查看仓库目录/文件

查看git仓库的目录结构,可以使用以下命令:

  • 1. `git ls-tree`: 显示指定提交(commit)或分支(branch)下的目录结构。

例如,要查看当前分支下的目录结构,可以使用以下命令:

git ls-tree -r HEAD 显示当前分支下所有文件和文件夹的信息,递归到子树


“git ls-tree HEAD“ 显示当前分支下所有文件和文件夹的信息,包括文件的类型、属主、对象(blob或tree)的SHA-1哈希值等。

  • 2. `git ls-files`: 这个命令可以显示包含在当前分支下的文件列表。例如,要查看当前分支下的所有文件,可以使用以下命令:

“git ls-files“ 显示当前分支下所有文件的相对路径

  • 3. `git cat-file`: 这个命令可以查看指定对象(blob或tree)的内容。例如,要查看某个文件的内容,可以使用以下命令:

“git cat-file -p <文件哈希值>“ 显示该文件的内容

cat readme.txt ,查看readme.txt的内容(实验发现是本地文件的内容,不是仓库中文件的内容)

  • 4. `git show`: 这个命令可以显示指定提交(commit)的详细信息,包括该提交下的所有文件变动。例如,要查看某个提交的详细信息,可以使用以下命令:

“git show <提交哈希值>“ 显示该提交中新增、修改和删除的文件

  • 5. `gitk`: 这是一个图形界面工具,可以可视化地查看git仓库的目录结构和提交历史。只需在命令行中输入 `gitk` 命令,就会打开一个窗口显示仓库的文件结构和提交历史。

通过以上这些命令和工具,你可以方便地查看git仓库的目录结构,并浏览仓库中的文件和文件夹。

👉版本管理

1、查看提交日志

git log 查看历史记录,显示从最近到最远的提交日志。

文件修改内容:

初始:(版本一)
Git is a version control system.
Git is free software.

第一次修改后:(版本二)
Git is a version control system.
Git is free software.
22222222
33333333

第二次修改后:(版本三)
Git is a version control system.
Git is free software.
22222222

如果嫌输出的信息太多,则可加上--pretty=oneline参数。

即,使用命令 git log --pretty=oneline 演示:

黄色一大串类似1094adb...的是commit id(版本号)。

和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示。commit id以自己的为准。

commit id需要用这么一大串数字表示是因为:

Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。

每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线。

2、版本回退

若想把当前的版本回退:

回退到上一个版本:git reset --hard HEAD^

回退到上上个版本:git reset --hard HEAD^^

回退到前100个版本:git reset --hard HEAD~100

注:

--hard会回退到上个版本的已提交状态,

--soft会回退到上个版本的未提交状态,

--mixed会回退到上个版本已添加但未提交的状态。

使用示例:(回退到上一个版本,也就是版本二)

cat readme.txt 查看readme.txt的内容

cat 是“concatenate”的缩写,意为“连接”或“串联”。其原意是用来将文件内容连接并输出到标准输出设备(通常是屏幕),被广泛用于查看文件内容

(此时查看文件内容发现,确实已经回退到上一个版本了。)

此时,再用 git log 查看历史记录信息,看下现在版本库的状态:

发现第二次修改的那个 “删除内容333333,只剩222” 看不到了。

若现在想回退到最新的版本(版本三),也就是刚刚看不到的那个版本,则可通过版本号进行回退。

git reflog 获取版本号

git reset --hard 版本号,用于回退到版本号对应的那个版本

(版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,否则Git可能会找到多个版本号,就无法确定是哪一个了。)

到此,已经又回到了最新那个版本(版本三)。

————

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针。

当你回退版本的时候,Git仅仅是把HEAD从指向(版本三),改为指向(版本二)。

然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。

  • 总结:
  1. HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
  2. 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
  3. 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本(利用其版本号)。

3、工作区和暂存区

工作区:就是在电脑上能看到的目录。比如:

  1. 目录下gitCxl里的文件(.git隐藏目录版本库除外)。
  2. 以后需要再新建的目录文件等等都属于工作区范畴。

版本库(Repository):工作区有一个隐藏目录.git,这个不属于工作区,而是Git的版本库。

  • 其中版本库里面存了很多东西,其中最重要的就是stage(暂存区),还有Git为我们自动创建了第一个分支master,以及指向master的一个指针HEAD。

我们前面说过使用Git提交文件到版本库有两步:

  • 第一步:是使用 git add 把文件添加进去,实际上就是把文件添加到暂存区。
  • 第二步:使用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支上。

因为创建Git版本库时,Git自动为我们创建了唯一一个master分支,

所以现在,git commit就是往master分支上提交更改。

可以简单理解为,需要提交的文件修改通通放到暂存区,然后一次性提交暂存区的所有修改。

  • demo演示如下:

修改 readme.txt 的内容,新增加 addnew.txt 文件。

1、先用命令 git status来查看下状态:

Git非常清楚地告诉我们:

  1. readme.txt被修改了;
  2. test.txt还从来没有被添加过,所以它的状态是Untracked

2、使用git add 命令把2个文件都添加到暂存区中,再使用git status来查看下状态:

add之后,此时两个文件皆处于暂存区中。

所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),

然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。

3、执行git commit就可以一次性把暂存区的所有修改提交到分支:

一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的,如上。

4、管理修改

Git跟踪并管理的是修改,而非文件。

  • 举个例子:

1、修改内容后使用 git add 添加到暂存区中;

2、在暂存区中 的前提下,再修改内容;

3、使用 git commit 提交到仓库。

也就是说,过程是【第一次修改 -> git add -> 第二次修改 -> git commit】 。

提交后会发现,第二次的修改并没有被提交。

  • 因为:

Git管理的是修改。

当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交

但是,在工作区的第二次修改并没有放入暂存区

所以,git commit只负责把暂存区的修改提交了

也就是第一次的修改被提交了,第二次的修改不会被提交。

————

提交后,

git diff HEAD -- readme.txt 可以查看工作区和版本库里面最新版本的区别,如上。

若提交第二次修改,可以:

【第一次修改 -> git add -> 第二次修改 -> git add -> git commit】

即可把第二次修改提交。

所以,每次修改,若不用git add到暂存区,则不会加入到commit中。

5、撤销修改

git checkout -- readme.txt 丢弃工作区的修改,把readme.txt文件在工作区做的修改全部撤销,有两种情况:(其实就是检出)(也可以把checkout换成resrore)

  1. 若自修改后未放到暂存区,则回退到版本库的状态;
  2. 若修改后已经放入暂存区,则回退到添加暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

————

撤销修改还有另外两种方法:

  1. 若知道要删掉哪些内容,可直接手动更改去掉那些需要的文件,然后add添加到暂存区,最后commit掉。
  2. 可以按以前的方法直接恢复到上一个版本。使用 git reset --hard HEAD^

使用示例:

1、在readme.txt文件里面增加一行内容为5555,通过cat命令查看文件内容,并用git statue查看下当前的状态如下:

2、用git checkout -- readme.txt 丢弃工作区的修改,把readme.txt文件在工作区做的修改全部撤销,并用cat查看文件内容,如下:

会发现工作区的修改 “增加的一行5555” 没了,也就是文件在工作区的修改已被撤销。(情况一)

再测试下情况二:

会发现撤销后,文件内容是回退到了暂存区中的状态,也就是情况二。

注意:命令git checkout -- readme.txt 中的 -- 很重要,若没有 -- 的话,则命令变成创建分支(切换到另一个分支)。

————

git reset HEAD readme.txt暂存区的修改撤销掉(unstage),重新放回工作区

git reset 命令既可回退版本,也可把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。

  • 总结:
  1. 场景1:当改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
  2. 场景2:当改乱了工作区某个文件的内容,且添加到了暂存区时,想丢弃修改,分两步:
    1. 第一步用命令git reset HEAD <file>,就回到了场景1,
    2. 第二步按场景1操作。
  3. 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节(回退到上一个版本:git reset --hard HEAD^),不过前提是没有推送到远程库。

6、删除文件

假如我现在版本库testgit目录添加一个文件b.txt,然后提交。如下:

直接在文件目录中把文件删了,或者使用如上rm命令:rm b.txt,此时工作区的b.txt文件已被删除

这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了,如下:

此时有两个选择:

  1. 一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit
  2. 另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本
  • 情况一:将版本库中的对应也删除

git rm b.txt 从版本库中删除 b.txt 文件,然后 git commit 提交,如下图:

注:

‘删除’也是一种‘修改’操作,先手动删除文件,然后使用 git add <file> 或者使用 git rm<file> 效果都是一样的。

  • 情况二:删错了,需从版本库中将对应文件恢复

git checkout -- b.txt 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

👉远程仓库

1、GitHub 中添加 SSH Key

需先注册github账号。

由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的,所以需要一点设置:

  • 第1步:创建SSH Key。

在用户主目录下,看看有没有 .ssh 目录。(C盘—>用户—>"用户名"—>.ssh文件夹)

如果有,再看看这个目录下有没有 id_rsa 和 id_rsa.pub 这两个文件,如果已经有了,可直接跳到下一步。

如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

ssh-keygen -t rsa -C "youremail@example.com"

把邮件地址换成自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。

若一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对。

id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人

  • 第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面

然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴 id_rsa.pub 文件的内容:

点击 Add Key,你就应该可以看到已经添加的key。

为什么GitHub需要SSH Key呢?
因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,
而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。

当然,GitHub允许你添加多个Key。
假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,
只要把每台电脑的Key都添加到GitHub,即可在每台电脑上往GitHub推送了。

最后友情提示,
在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。
所以,不要把敏感信息放进去。

如果你不想让别人看到Git库,有两个办法:
一个是交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。
另一个办法是自己动手,搭一个Git服务器,因为是你自己的Git服务器,所以别人也是看不见的。
自己动手搭Git服务器这个方法我们后面会讲到的,相当简单,公司内部开发必备。

2、添加远程库

如何添加远程库?
现在的情景是:

我们已经在本地创建了一个Git仓库后,又想在github创建一个Git仓库,并且希望这两个仓库进行远程同步,这样github的仓库可以作为备份,又可以其他人通过该仓库来协作。

  • 首先,登录github上,然后在右上角找到“create a new repo”创建一个新的仓库。如下:

  • 在Repository name填入testgit,其他保持默认设置,点击“Create repository”按钮,就成功地创建一个新的Git仓库

目前,在GitHub上的这个testgit仓库还是空的,GitHub告诉我们:

可以从这个仓库克隆出新的仓库,

也可以把一个已有的本地仓库与之关联,然后把本地仓库的内容 推送到GitHub仓库。

现在,我们根据GitHub的提示,在本地的 gitCxl 仓库下运行命令:

git remote add origin https://github.com/chxin14160/gitCxl.git

千万注意,把上面的 chxin14160 替换成自己的GitHub账户名。

否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,

因为你的SSH Key公钥不在我的账户列表中。

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

  • 下一步,就可以把本地库的所有内容推送到远程库上

把本地库的内容推送到远程,使用 git push 命令,实际上是把当前分支master推送到远程

git push -u origin master 初次提交,把本地master分支的最新修改推送到github上

由于远程库是空的,我们第一次推送master分支时,加上了 –u参数,Git

不但会把本地的master分支内容推送到远程新的master分支,

还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

推送成功后,可以立刻在github页面中看到远程库的内容已经和本地一模一样了,上面的要输入github的用户名和密码如下所示:

从现在起,只要本地作了提交,就可以通过如下命令:

git push origin master

把本地master分支的最新修改推送到github上了,现在你就拥有了真正的分布式版本库了。


SSH警告

当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:

The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?

这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。

Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:

Warning: Permanently added 'github.com' (RSA) to the list of known hosts.

这个警告只会出现一次,后面的操作就不会有任何警告了。

如果你实在担心有人冒充GitHub服务器,输入yes前可以对照GitHub的RSA Key的指纹信息是否与SSH连接给出的一致。


删除远程库

如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>命令。使用前,建议先用git remote -v查看远程库信息:

$ git remote -v
origin  git@github.com:michaelliao/learn-git.git (fetch)
origin  git@github.com:michaelliao/learn-git.git (push)

然后,根据名字删除,比如删除origin

$ git remote rm origin

此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。

要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。


  • 总结
  1. 关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
  2. 关联一个远程库时必须给远程库指定一个名字,origin是默认习惯命名;
  3. 关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
  4. 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改

分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作。

而SVN在没有联网的时候是拒绝干活的!

GitHub当有网络的时候,再把本地提交推送一下即可完成同步。

3、从远程库克隆

如何从远程库克隆?

上面我们了解了先有本地库,后有远程库时候,如何关联远程库

  1. 登录github,创建一个新的仓库 gitCxl;
  2. 在本地的 gitCxl 仓库下运行命令 git remote add origin https://github.com/chxin14160/gitCxl.git,关联GitHub仓库;
  3. 初次提交,使用 git push -u origin master 把本地库的所有内容推送到远程库上 (实际上是把当前分支master推送到远程);
  4. 后续提交,皆只需使用 git push origin master 把本地master分支的最新修改推送到github上。

现在,远程库有新内容,想将其克隆到本地来,如何克隆呢?

  • 首先,登录github,创建一个新的仓库,名字叫 gitCxl2 ,如下:

勾选Initialize this repository with a README,GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件。

  • 此时,远程库已经准备好了,下一步是使用命令git clone克隆一个本地库了。如下所示:

git clone https://github.com/chxin14160/gitCxl2 从GitHub的对应地址中克隆一个本地库

如此,本地目录下便会生成生成 gitCxl2 目录了,如下所示:

若有多个人协作开发,则每个人各自从远程克隆一份即可。

GitHub给出的地址不止一个,

还可以用

格式1:https://github.com/michaelliao/gitskills.git 

格式2:git clone git@github.com:michaelliao/gitskills.git 

以上两种格式的地址写法。

实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。

使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令。

但是在某些只开放http端口的公司内部就无法使用ssh协议,而只能用https。

  • 总结:
  1. 要克隆一个仓库,需知道仓库的地址,然后使用git clone命令克隆。
  2. Git支持多种协议,包括https,但ssh协议速度最快。

其余克隆仓库方法:

克隆 Git 中的所有分支 | D栈 - Delft Stack

4、比较本地仓库和远程仓库的差异并更新本地仓库(实践版)

链接:git比较本地仓库和远程仓库的差异并更新本地仓库(实践版)-CSDN博客

5、本地提交远程库时被拒绝(解决方法)

报错显示:

分析:

  • 这个错误表明你的本地 master 分支和远程 github 仓库的 master 分支存在冲突。
  • 远程仓库有新的提交(可能是你自己或其他协作者推送的),
  • 而你的本地分支没有这些更新。Git 拒绝直接推送以避免覆盖远程的更改。
解决方法1:先拉取远程更改并合并

运行以下命令将远程的更改拉取到本地并自动合并:

git pull github master

如果合并时有冲突,需要手动解决冲突后提交:

git add .          # 标记冲突已解决
git commit -m "fix merge conflicts"

然后重新推送:

git push github master
解决方法2:强制推送(谨慎使用)

如果确定远程的更改可以丢弃(例如是你自己之前误操作导致的),可以强制推送:

git push --force github master

⚠️ 注意:强制推送会覆盖远程历史,可能导致其他协作者的工作丢失,仅限个人项目或确认安全时使用。

解决方法3:变基(Rebase)替代合并

如果希望保持提交历史线性,可以在拉取时使用 --rebase

git pull --rebase github master
git push github master

关键原因:

  • 远程仓库的 master 分支有你本地不存在的提交(例如通过 GitHub 网页直接修改文件)。
  • Git 默认要求推送前保持历史一致,避免覆盖他人工作。

预防措施:

  • 推送前先拉取最新更改:git pull github master
  • 定期同步远程分支,尤其是在协作开发时。

如果仍有问题,可以检查远程分支状态:

git fetch github          # 获取远程最新信息
git log github/master     # 查看远程提交历史
git log master            # 查看本地提交历史

👉分支管理

1、创建与合并分支

在版本回退里,已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。

截止到目前只有一条时间线,在Git里,这个分支叫主分支,即master分支。

HEAD严格来说不是指向提交,而是指向master。master才是指向提交的。

所以,HEAD指向的就是当前分支

创建分支dev,同时切换到dev上:

由于此时已切换到分支dev上,任何修改皆是针对dev:

最简单粗暴的将dev合并到master上,是直接将master指针指向dev:

删除dev,就是直接将dev的指针删掉:

下面开始实战。

  • 首先,创建dev分支,然后切换到dev分支上。如下操作:

git checkout -b dev 创建并切换分支dev

git checkout 命令加上-b参数表示创建并切换,相当于以下两条命令:

git branch dev 创建分支dev
git checkout dev 切换分支dev

$ git branch dev
$ git checkout dev
Switched to branch 'dev'
  • 然后,用git branch命令查看当前分支

git branch 查看分支,会列出所有的分支,当前分支前面会添加一个星号 “ ”。

  • 然后,我们在dev分支上继续做demo,并正常提交

比如,我们现在 在readme.txt再增加一行 7777。

首先我们先来查看下readme.txt内容,接着添加内容77777777,如下:

此时,dev分支上的内容已提交,也就是dev分支的工作已完成。

  • 现在我们主分支master上,继续查看readme.txt内容如下:

git checkout master 切换到分支master

切回master后发现dev分支修改的7777不见了。

因为7777的修改提交在了dev分支上,而此时master分支的提交点并没有变:

  • 现在我们可以把dev分支上的工作成果,也就是内容合并到主分支master上了。

可以在master分支上,使用如下命令 git merge dev 如下所示:

可以看到,将dev合并进来之后,master的readme中多了一条7777。

git merge 命令用于合并指定分支到当前分支上。

合并后,再查看readme.txt内容,可以看到,和dev分支最新提交的是完全一样的。

ps:注意到上面的 Fast-forward 信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

  • 合并完成后,我们可以接着删除dev分支了,操作如下:

git branch –d dev 删除分支dev

删除后,git branch 查看分支,就只剩下master分支了,如上图。

因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

————

switch

我们注意到切换分支使用git checkout <branch>

而前面讲过的撤销修改则是git checkout -- <file>

同一个命令,有两种作用,确实有点令人迷惑。

实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:

创建并切换到新的dev分支,可以使用:

$ git switch -c dev

直接切换到已有的master分支,可以使用:

$ git switch master

使用新的git switch命令,比git checkout要更容易理解。

  • 总结 创建与合并分支 命令如下
查看分支:git branch
创建分支:git branch name
切换分支:git checkout name 或者 git switch name
创建+切换分支:git checkout –b name 或者 git switch -c <name>
合并某分支到当前分支:git merge name
删除分支:git branch –d name

2、解决冲突

  • 先制造冲突测试demo
  1. git checkout -b fenzhi1 先创建并切换到分支fenzhi1
  2. cat readme.txt 查看增加内容前的readme
  3. readme中增加内容8888
  4. 继续查看增加内容后的readme
  5. 将readme添加到暂存区,并提交到仓库(此时仍在分支fenzhi1上)

  • 在分支fenzhi1中提交修改内容后,切换回分支master

在分支master中也在最后一行添加内容,内容为9999,如下所示:

此时,master分支 和 fenzhi1分支 各自都分别有新的提交,变成了这样:

  • 现在我们需要在master分支上来合并fenzhi1,如下操作:

(两个分支都分别有各自的提交,这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。)

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中:

<<<<<<<HEAD 是指主分支修改的内容;

>>>>>>>fenzhi1 是指fenzhi1上修改的内容;

我们可以修改如下后保存,再提交:

此时,master分支 和 feature1分支 变成了下图所示:

  • 若想查看分支合并的情况的话,需要使用命令 git log 命令行演示如下:

或者用带参数的git log也可以看到分支的合并情况:

git log --graph --pretty=oneline --abbrev-commit

git log 命令是 Git 版本控制系统中用于显示项目提交历史记录的命令。通过添加不同的选项,你可以定制输出的格式和包含的信息。下面是对你提到的命令选项的解释:

--graph:这个选项会在输出中显示一个 ASCII 图形,用以表示分支和合并的历史。图形中的每一行代表一个提交,分支点会以竖线(|)和分叉(* 或 /)来表示。这使得你可以直观地看到项目的分支和合并情况。
--pretty=oneline:这个选项将每个提交的记录格式化为单行显示。默认情况下,git log 会显示每个提交的哈希值、作者、日期和提交信息。使用 --pretty=oneline,只会显示提交的哈希值(通常是简短的,如果使用了 --abbrev-commit 选项)和提交信息,而且这两部分会在一行内显示,便于快速浏览。
--abbrev-commit:这个选项会让 Git 使用简短的提交哈希值(通常是前几个字符)而不是完整的 40 个字符的哈希值。这样做可以减少输出的长度,使得输出更加简洁。
综上所述,git log --graph --pretty=oneline --abbrev-commit 命令的作用是:以单行格式简洁地显示项目的提交历史,包括简短的提交哈希值和提交信息,并且使用 ASCII 图形表示分支和合并的历史。这个命令非常适合快速查看项目的提交历史和分支结构。

最后,可以删除 fenzhi1 分支

git branch -d fenzhi1

  • 总结
  1. 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
  2. 解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交
  3. git log --graph命令可以看到分支合并图。

3、分支管理策略

通常合并分支时,git一般使用”Fast forward”模式,在这种模式下,删除分支后,会丢掉分支信息。

现在我们来使用带参数 –no-ff 的 git  merge 来强制禁用”Fast forward”模式。

(如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。)

git merge --no-ff -m "merge with no-ff" dev 合并,但是禁用 fast forward 模式

demo演示如下:

  1. 创建一个dev分支。
  2. 修改readme.txt内容。
  3. 添加到暂存区,并commit提交。
  4. 切换回主分支(master)。
  5. 合并dev分支,使用命令 git merge –no-ff -m “注释” dev
  6. 查看历史记录

截图如下:

可以看到,不使用Fast forward模式,merge后就像这样:

(与前面的解决冲突后 合并的流程图其实是一样的)
  • 分支策略:

首先master主分支应该是非常稳定的,也就是用来发布新版本,平时不能在上面干活。

干活一般情况下在新建的dev分支上干活,干完后,比如说要发布,或者说dev分支代码稳定后可以合并到主分支master上来。

  • 即:

master主分支为确保ok的可发布的,不用于干活;

干活在新建的dev分支上干,若稳定了或要发布了,则可合并到master主分支中。


每个小伙伴都在dev分支上干活,

每个人都有自己的分支,

时不时地往dev分支上合并即可。

所以,团队合作的分支看起来就像这样:

  • 总结:
  1. Git分支十分强大,在团队开发中应该充分应用。
  2. 合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

4、Bug分支

在开发中,会经常碰到bug问题,那么有了bug就需要修复,

在Git中,分支是很强大的,每个bug都可以通过一个新的临时分支来修复,

修复完成后,合并分支,然后将临时的分支删除掉。

(当前工作区有文件未提交,此时想切换分支如果有同一文件会冲突)

  • demo测试流程:
  1. 创建并切换dev分支,且在readme中添加内容“working”;
  2. 查看当前状态(位于dev分支,修改未提交,readme有修改);
  3. git stash 将当前工作现场隐藏起来,并查看状态;
  4. 因为是要在master上修复bug,所以先切换回master分支;
  5. 创建并切换 issue-404 分支,用于临时改bug (准备在issue-404分支上改bug);
  6. 查看修改前的readme内容;
  7. readme中添加内容 “fixBug”,并查看修改后的内容;
  8. 将修完bug后的readme添加到暂存区并提交;
  9. 此时已修好bug,再切换回master分支上,并完成合并后删除 issue-404分支;
  10. 此时可切换回dev分支继续干活了,先切换到dev分支并查看状态;
  11. git stash list 查看stash了那些内容;
  12. 将stash的内容(默认为第一项)恢复;
  13. 将stash的内容(默认为第一项)删除,删除后再次查看stash里的内容。

比如:

在开发中接到一个 404 bug 时,可以创建一个 issue-404 分支来修复它,

但是,当前的dev分支上的工作还没有提交。比如如下:

流程1、2

流程1:创建并切换dev分支,且在readme中添加内容“working”;

流程2:查看当前状态(位于dev分支,修改未提交,readme有修改); 

并不是不想提交,而是工作进行到一半时候,暂时还无法提交。

比如我这个分支bug要2天完成,但是我issue-404 bug需要5个小时内完成。怎么办呢?

还好,Git还提供了一个stash功能,可以把当前工作现场 ”隐藏起来”,等以后恢复现场后继续工作。如下:

git stash 将当前工作现场隐藏起来(可多次使用)

(将本地没提交的内容(git commit的内容不会被缓存 但git add的内容会被缓存)进行缓存并从当前分支移除,缓存的数据结构为堆栈,先进后出)

git stash 只能缓存被跟踪的文件,本次新增的文件并不能被缓存,需要先 add 进暂存区之后才能被缓存

流程3

流程3: git stash 将当前工作现场隐藏起来,并查看状态;

所以,现在可以通过创建issue-404分支来修复bug了。

首先我们要确定在哪个分支上修复bug,

比如我现在是在主分支master上来修复的,现在我要在master分支上创建一个临时分支,演示如下:

流程4~8

流程4:因为是要在master上修复bug,所以先切换回master分支;

流程5:创建并切换 issue-404 分支,用于临时改bug (准备在issue-404分支上改bug);

流程6:查看修改前的readme内容;

流程7:readme中添加内容 “fixBug”,并查看修改后的内容;

流程8:将修完bug后的readme添加到暂存区并提交; 

修复完成后,切换到master分支上,并完成合并,最后删除issue-404分支。演示如下:

流程9

流程9:此时已修好bug,再切换回master分支上,并完成合并后删除 issue-404分支;

现在,可以回到dev分支上干活了。

流程10

流程10: 此时可切换回dev分支继续干活了,先切换到dev分支并查看状态;

工作区是干净的,那么我们工作现场去哪里呢?我们可以使用命令 git stash list来查看下。如下:

git stash list 查看stash了哪些存储,每一行的冒号前面的字符串就是标识此隐藏的id

流程11

流程11: git stash list 查看stash了那些内容;

工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,可以使用如下2个方法:

  1. git stash apply恢复,恢复后,stash内容并不删除,需要使用命令git stash drop来删除。
  2. 另一种方式是使用git stash pop,恢复的同时把stash内容也删除了。

演示如下:

git stash apply 恢复stash的内容(默认为第一个)

git stash apply stash@{1} 恢复第二个stash的内容(因为下标从0开始)

git stash drop 删除stash的内容(默认为第一个)

git stash pop 恢复的同时把stash内容也删除(默认为第一个stash,即stash@{0}。)

(将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下)

如果要应用并删除其他stash,命令:

git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1})

流程11~13

流程11: git stash list 查看stash了那些内容;

流程12: 将stash的内容(默认为第一项)恢复;

流程13: 将stash的内容(默认为第一项)删除,删除后再次查看stash里的内容。

删除后再查看,就看不到任何stash内容了,如上图。


前面修复了master上的bug,但由于dev分支就是早期从master分支分出来的,因此这个bug其实在当前dev分支上也存在。

所以当前需要在dev上修复同样的bug。

但可以无需重复操作一次,

前面可以看到修复完bug时,提交的那个id号为d890941

因此,只需把 d890941 fix bug 404 这个提交所做的修改“复制”到dev分支即可。

git cherry-pick d890941 把提交编号为d890941所做的修改全部复制到当前所在分支

id 是commit的id,所以git cherrypick id是复制了commit操作。

相当于把修改又提交了一次。当然是同样的修改,复制了一份,id是不同的。

我的演示效果如上图。

因为fixbug和working位于同一行,所以我在执行git cherry-pick 时出现了与合并一样的冲突。

按照解决冲突的方式解决并重新add和commit即可。

  • 总结:
  1. 需要修复bug时,可以通过创建新的bug分支来进行修复,然后合并,最后删除;
  2. 当手头工作未完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;
  3. 在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。

将分支b中的指定的提交内容同步到分支a中

# 1. 在开发分支工作树中确认改动
cd E:\git\GalvanoCalibrationTree_calibration_codex
git status

# 2. 暂存第 1 批文件,并检查暂存内容
git add UI/Include/UI/ScannerCalibrationExport.h UI/Src/ScannerCalibrationExport.cpp UI/Tests/CircleDetectionReportTests.cpp
git diff --cached --check

# 3. 创建第 1 个本地提交
git commit -m "新增功能:生成可直接导入的扫描仪校准Template"

# 4. 暂存第 2 批文件并创建第 2 个本地提交
git add UI/Include/UI/ScannerCalibrationExportDialog.h UI/Src/ScannerCalibrationExportDialog.cpp UI/Tests/MainWindowToolbarTests.cpp
git commit -m "优化:校准依据默认使用400机型并自动定位最新圆检测结果"

# 5. 切到 calibration 所在工作树,先确认没有未提交改动
cd E:\git\GalvanoCalibration
git status

# 6. 将开发分支的两笔提交追加到本地 calibration
git cherry-pick d3d6500 baa03dd

# 7. 确认同步结果
git log -3 --oneline
git status

5、Feature分支

当代码需要添加新功能时,为了不把主分支搞乱,可以先新建一个feature分支,在其上面开发,完成后与主分支进行合并,合并完最后将该feature分支删除。

具体流程如下:

  1. 新建并切换到feature分支;
  2. 在feature分支下进行开发,然后add和commit,中途可查看状态;
  3. 切换回dev分支;
  4. 若需合并,则合并方式与bug分支是类似的;
  5. 若接到通知说要将分支立即销毁,则可使用 git branch -D feature-tmp 强行删除分支。
流程1、2

流程1:新建并切换到feature分支;

流程2:在feature分支下进行开发,然后add和commit,中途可查看状态;

流程3:切换回dev分支

使用 git branch -d feature-tmp 删除feature-tmp分支会提示如下:

$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.

销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数。

git branch -D feature-tmp 强行删除feature-tmp分支

流程5:强行删除feature-tmp分支

删除成功,如上图。

  • 总结:
    • 如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

6、多人协作

当你从远程仓库克隆时,

实际上Git自动把本地的master分支和远程的master分支对应起来了,

并且,远程仓库的默认名称是origin

要查看远程库的信息 使用 git remote
要查看远程库的详细信息 使用 git remote –v

如下演示:

上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

先将前面的dev合并到master上,然后加入暂存区并提交。
此时本地readme.txt的内容如上

(一)推送分支

推送分支:就是把该分支上所有本地提交到远程库中。

推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
使用命令 git push origin master 将本地的master分支推送到远程库对应的远程分支上

比如我现在的github上的readme.txt代码以及本地的readme.txt代码如下:

使用命令 git push origin master 将本地的master分支推送到远程库对应的远程分支上

也就是把本地更新的readme.txt代码推送到远程库中:

可以看到如上,推送成功。

此时,github上的readme.txt内容 如下:

可以看到 推送成功了。

再尝试将dev分支推送到远程库中:

git push origin dev

同样的,也推送成功了。

关于哪些分支需要往远程推送,哪些不需要:

  • master分支是主分支,因此要时刻与远程同步;
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程,可以先合并到主分支上,然后把主分支master推送到远程去;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!

即,maser要,dev要,bug没必要,feature看情况。

(二)抓取分支

多人协作时,大家都会往master分支上推送各自的修改。现在我们可以模拟另外一个同事:

可以在另一台电脑上(注意要把SSH key添加到github上)

或者同一台电脑上另外一个目录克隆,新建一个目录名字叫testgit2。

但是我首先要把dev分支也要推送到远程去,如下

接着进入testgit2目录,进行克隆远程的库到本地来,如下:

git clone https://github.com/chxin14160/gitCxl 克隆远程仓库地址https://github.com/chxin14160/gitCxl到本地

注意:

以上为普通克隆方式,默认情况下,你的小伙伴只能看到本地的master分支。

因为默认克隆 默认的那个分支(通常是main,也有可能是master,默认是哪个可自行更改),且只有默认那个分支。

切换到队友的目录然后克隆远程库
克隆远程库到队友目录上

现在目录下生成有如下所示:

若小伙伴要在dev分支上做开发,就必须 创建远程origin的dev分支 到本地来。

于是可以使用命令创建本地dev分支:git checkout –b dev origin/dev

现在小伙伴们就可以在dev分支上做开发了,开发完成后把dev分支推送到远程库时。

如下:

队友完成修改后提交上仓库
队友将修改内容提交到远程仓库

小伙伴们已经向origin/dev分支上推送了提交,而我在我的目录文件下也对同样的文件同个地方作了修改,也试图推送到远程库时,如下:

回到自己的工程路径,同样修改后提交到仓库

 

由上面可知:推送失败。

因为,我的小伙伴最新提交的和我试图推送的有冲突。

解决的办法也很简单,上面已经提示我们:

先用git pull 把最新的提交从远程origin/dev抓取下来,然后在本地合并,解决冲突,再推送。

git pull也失败了,原因是:

没有指定本地 dev分支与远程 origin/dev分支的链接。

根据提示,设置dev和origin/dev的链接:如下:

git branch --set-upstream-to=origin/dev dev 指定本地dev分支与远程origin/dev分支的链接

git branch --set-upstream branch-name origin/branch-name 作用同上,建立本地分支和远程分支的关联

这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的 解决冲突完全一样。

解决后,提交,再push:
先看与队友代码存在冲突时的readme.txt内容了:

现在已经手动解决完冲突了,接着需要再提交,再push到远程库里面去。如下所示:

此时可以看到,重新push后哪个推送成功了,如上图。

————

因此:多人协作工作模式一般流程如下:

  1. 首先,可以试图用 git push origin dev 推送自己dev分支的修改;
  2. 若推送失败,则因为远程分支比自己的本地更新早,需要先用 git pull 试图合并。
  3. 若合并有冲突,则需要解决冲突,并在本地commit提交。再用git push origin dev推送dev分支。

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。

  • 总结:
  1. 查看远程库详细信息,使用 git remote -v;
  2. 本地新建的分支若不推送到远程,对其他人就是不可见的;
  3. 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
  4. 在本地创建和远程分支对应的分支,使用 git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
  5. 建立本地分支和远程分支的关联,使用 git branch --set-upstream dev origin/dev 或 git branch --set-upstream-to=origin/dev dev;
  6. 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突,成功合并完再重新commit然后重新git push。

7、Rebase

  • 在个人分支整理、同步上游更新时,用于整理提交历史,保持直线。

上一节可以看到:

多人在同一个分支上协作时,很容易出现冲突。

即使没有冲突,后push的人也不得不先pull,在本地合并,然后才能push成功。

参考链接:git rebase详解(图解+最简单示例,一次就懂)-CSDN博客

打个比方

master为主分支,feature为在节点B开始从master分出来的分支。则:

  • feature:待变基分支、当前分支
  • master:基分支、目标分支

分叉后master修改了一次位于节点M,分叉后feature修改过两次分别位于节点C和D。

效果:

当在feature分支上执行git rebase master时:

  1. git会从master和featuer的共同祖先B开始提取feature分支上的修改,也就是C和D两个提交,先提取到。
  2. 然后将feature分支指向master分支的最新提交上,也就是M。
  3. 最后把提取的C和D接到M后面。

注意这里的接法,官方没说清楚,实际是会依次拿M和C、D内容分别比较,处理冲突后生成新的C’和D’。一定注意,这里新C’、D’和之前的C、D已经不一样了,是我们处理冲突后的新内容,feature指针自然最后也是指向D’。

  • 总结

rebase,变基,可以直接理解为改变基底。

feature分支是基于master分支的B拉出来的分支,feature的基底是B。

而master在B之后有新的提交,就相当于此时要用master上新的提交来作为feature分支的新基底。

实际操作为把B之后feature的提交先暂存下来,然后删掉原来这些提交,再找到master的最新提交位置,把存下来的提交再接上去(接上去是逐个和新基底处理冲突的过程),

如此,feature分支的基底就相当于变成了M而不是原来的B了。

(注意,如果master上在B以后没有新提交,那么就还是用原来的B作为基,rebase操作相当于无效,此时和git merge就基本没区别了,差异只在于git merge会多一条记录Merge操作的提交记录)

  • 使用场景
    • 拉公共分支最新代码——rebase;
    • 往公共分支上合代码——merge
    • 正因如此,大部分公司其实会禁用rebase,不管是拉代码还是push代码统一都使用merge,虽然会多出无意义的一条提交记录“Merge … to …”,但至少能清楚地知道主线上谁合了的代码以及他们合代码的时间先后顺序

所以就是,没有特殊需求,都用merge,避免用rebase!!!

—— rebase相关命令:git rebase -i HEAD~3   修改最近3次提交中的某一次

  • -i 是 interactive(交互式);
  • HEAD~3 就是"往前数 3 个提交"
  • HEAD~5 就是 表示涵盖最近5次提交,确保能覆盖到某条 Merge 提交

把最近 3 次提交拿出来,重新编辑:git rebase -i HEAD~3

修改最近 5 次提交中的某一次:git rebase -i HEAD~5

具体例子:

假设最近提交了3次:用 git log --oneline 可看到:

abc123 第三次提交:修复bug
def456 第二次提交:添加功能
ghi789 第一次提交:初始化

现在想修改第二次提交("添加功能"那次),把里面某个文件改一下。

  1. 第一步:启动交互式 rebase
    git rebase -i HEAD~3

    这时候 Git 会弹出一个编辑窗口(可能是 Vim 或你配置的编辑器),长这样:

    pick ghi789 第一次提交:初始化
    pick def456 第二次提交:添加功能
    pick abc123 第三次提交:修复bug
  2. 第二步:告诉 Git 你要改哪个→ 把想改的那行前面的 pick 改成 edit(或 e):
    pick ghi789 第一次提交:初始化
    edit def456 第二次提交:添加功能    ← 改这里
    pick abc123 第三次提交:修复bug

    保存退出。

  3. 第三步:Git 会停在指定的那个→ 终端会显示类似这样的信息:
    Stopped at def456... 第二次提交:添加功能
    You can amend the commit now, with:
      git commit --amend

    这时候就回到了那个提交的时刻,可以随便改文件了。

    比如发现某个文件写错了:

    # 修改文件
    vim somefile.js
    
    # 把修改加进暂存区
    git add somefile.js
    
    # 修改这次提交
    git commit --amend

    git commit --amend 会让你重新编辑提交信息,改完保存退出就行。

  4. 第四步:继续完成 rebase提交
    git rebase --continue

    Git 会接着处理后面的提交,直到全部完成。


若想改的是"提交信息"而非内容

更简单,第二步里把 edit 换成 reword(或 r)即可:

reword def456 第二次提交:添加功能

Git 会停下来让你改提交信息,改完自动继续,不用手动 amend

  • 整体流程总结:
    git rebase -i HEAD~3
        ↓
    编辑窗口:把 pick 改成 edit/reword/squash...
        ↓
    保存退出
        ↓
    Git 停在目标提交 → 你修改内容 → git add → git commit --amend
        ↓
    git rebase --continue
        ↓
    完成 ✅

👉标签管理

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。

将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。

所以,标签也是版本库的一个快照。

Git的标签其实就是指向某个commit的指针,且不能移动,所以创建和删除标签都是瞬间完成的。(标签可以用版本号标识,如tag v1.2)

1、创建标签

在Git中打标签非常简单,首先,切换到需要打标签的分支上:

(假设我现在要在master上打标签)

git branch

git checkout master

然后,敲命令git tag <name>就可以打一个新标签:

git tag v1.0 给当前分支打上标签v1.0

然后可以用命令 git tag 查看所有标签,如下图:

默认标签是打在最新提交的commit上的。

有时候,如果忘了打标签,比如,现在已是周五了,但该在周一打的标签没有打,怎么办?

方法是:找到历史提交的commit id,然后打上即可:

git log --pretty=oneline --abbrev-commit 查找历史提交的commit id

(比方说要对 merge bug fix 404 with no ff 这次打标签,其对应的commit id是0f3d70b)

git tag v0.9 0f3d70b  给commit id为0f3d70b的这次commit打上标签为v0.9

  • --abbrev-commit:让 Git 在显示提交的哈希值时,只显示哈希值的前几个字符(默认是7个字符,但可能因 Git 版本而异)。因为完整的哈希值非常长(40个字符),显示简短的哈希值既节省空间,又便于阅读。

git log --pretty=oneline --abbrev-commit 以每行一个提交 的方式显示项目的提交历史,每个提交显示其简短的哈希值和提交消息的开头部分。

  • 注意:标签不是按时间顺序列出,而是按字母排序的

可以用git show <tagname>查看标签信息:

git show v0.9 查看标签为v0.9的commit信息

可以看到,v0.9确实打 在merge bug fix 404 with no ff 这次提交上,如上图。

还可以创建带有说明的标签,用-a指定标签名-m指定说明文字即注释

git tag -a v0.6 -m "添加a文件" 06b9341

(创建带有说明的标签)给commit id为06b9341的这次commit打上标签为v0.6,注释详细为"添加a文件"

  • 注意:
    • 标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
  • 总结
  1. 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id 如 git tag v0.9 0f3d70b;
  2. 命令git tag -a <tagname> -m "注释"可以指定标签信息;
  3. 命令git tag可以查看所有标签;
  4. 命令git show <tagname>查看标签信息。

拓展参考链接:Git - 打标签

2、操作标签

  • 若标签打错了,也可以删除标签(本地的)

git tag -d v0.5 删除本地标签v0.5

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。

  • 如果要推送某个标签到远程,使用命令git push origin <tagname>

git push origin v1.0 将标签v1.0推送到远程库

此时远程库中的标签显示如下:

  • 或者,一次性推送全部尚未推送到远程的本地标签

git push origin --tags 一次性推送全部尚未推送到远程的本地标签到远程

此时远程库中的标签显示如下:

  • 如果标签已经推送到远程,要删除远程标签就麻烦一点(先从本地删除,再从远程删除)。

先从本地删除:

 git tag -d v0.9

再从远程删除。删除命令也是push,但是格式如下:

git push origin :refs/tags/v0.9 从名为 origin 的远程仓库中删除名为 v0.9 的标签

  • :(冒号)表示删除操作。
    • 在 Git 中,使用 : 前缀一个引用(ref)通常意味着要删除该引用。
      • 如果后面跟着的是分支名,表示删除远程分支;
      • 如果跟着的是标签名(在 refs/tags/ 路径下),则表示删除远程标签。
  • refs/tags/v0.9 是 Git 中标签的完整引用路径。
    • 在 Git 中,分支和标签都被视为引用,
      • 分支存储在 refs/heads/ 路径下;
      • 标签存储在 refs/tags/ 路径下
    • 这里的 v0.9 是标签的名称,refs/tags/ 是所有标签的前缀路径。

要看看是否真的从远程库删除了标签,可以登陆GitHub查看远程库中的标签状态:

  • 总结:
  1. 命令git push origin <tagname>可以推送一个本地标签;
  2. 命令git push origin --tags可以推送全部未推送过的本地标签;
  3. 命令git tag -d <tagname>可以删除一个本地标签;
  4. 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。
  5. 注:要删除已推送到远程的 远程标签,需先从本地删除,然后再从远程删除。

👉使用GitHub

GitHub是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人的开源项目。

参与开源项目

1、先访问别人开源的bootstrap项目主页;

2、点“Fork”,在自己的账号下克隆了一个a仓库;

3、从自己的账号下clone:git clone git@github.com:chxin14160/bootstrap.git

(一定要从自己的账号下clone仓库,才能推送修改。如果从bootstrap的作者的仓库地址git@github.com:twbs/bootstrap.git克隆,会因为没有权限,而导致不能推送修改。)

Bootstrap的官方仓库twbs/bootstrap、你在GitHub上克隆的仓库my/bootstrap,以及你自己克隆到本地电脑的仓库,他们的关系就像下图显示的那样:

  • 若想修复bootstrap的一个bug,或者新增一个功能,立刻就可以开始干活,干完后,往自己的仓库推送。
  • 若希望bootstrap的官方库能接受你的修改,则可以在GitHub上发起一个pull request。当然,对方是否接受你的pull request就不一定了。

总结

  • 在GitHub上,可以任意Fork开源仓库;
  • 自己拥有Fork后的仓库的读写权限;
  • 可以推送pull request给官方仓库来贡献代码。

👉使用Gitee

和GitHub相比,Gitee也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示等功能。

对于团队协作开发,Gitee还提供了项目管理、代码托管、文档管理的服务,5人以下小团队免费。

1、Gitee 中添加 SSH Key

使用Gitee和使用GitHub类似,我们在Gitee上注册账号并登录后,需要先上传自己的SSH公钥。选择右上角用户头像 -> 菜单“设置”,然后在左侧菜单选择“SSH公钥”,填写一个便于识别的标题,然后把用户主目录下的.ssh/id_rsa.pub文件的内容粘贴进去:

点击“确定”即可完成并看到刚才添加的Key:

2、已有本地库,关联远程库(先解绑GitHub)

若已有一个本地的git仓库(例如,一个名为learngit的本地库),想把它关联到Gitee的远程库上。

首先,我们在Gitee上创建一个新的项目,选择右上角用户头像旁的加号,然后点击“新建仓库”:

项目名称最好与本地库保持一致。

然后,我们在本地库上使用命令git remote add把它和Gitee的远程库关联:

$ git remote add origin git@gitee.com:liaoxuefeng/learngit.git

之后,就可以正常地用git pushgit pull推送了!

如果在使用命令git remote add时报错:

git remote add origin git@gitee.com:liaoxuefeng/learngit.git
fatal: remote origin already exists.

这说明本地库已经关联了一个名叫origin的远程库。

此时,可以先用git remote -v查看远程库信息:

git remote -v
origin	git@github.com:michaelliao/learngit.git (fetch)
origin	git@github.com:michaelliao/learngit.git (push)

可以看到,本地库已经关联了origin的远程库,并且,该远程库指向GitHub。

我们可以删除已有的GitHub远程库:

git remote rm origin

再关联Gitee的远程库(注意路径中需要填写正确的用户名):

git remote add origin git@gitee.com:liaoxuefeng/learngit.git

此时,我们再查看远程库信息:

git remote -v
origin	git@gitee.com:liaoxuefeng/learngit.git (fetch)
origin	git@gitee.com:liaoxuefeng/learngit.git (push)

现在可以看到,origin已经被关联到Gitee的远程库了。通过git push命令就可以把本地库推送到Gitee上。

3、已有本地库,既关联GitHub,又关联Gitee

一个本地库可以既关联GitHub,又关联Gitee。

因为git本身是分布式版本控制系统,可以同步到另外一个远程库,当然也可以同步到另外两个远程库。

使用多个远程库时,我们要注意:

git给远程库起的默认名称是origin

若有多个远程库,则需要用不同的名称来标识不同的远程库

仍然以learngit本地库为例,我们先删除已关联的名为origin的远程库:

git remote rm origin

然后,先关联GitHub的远程库:

git remote add github git@github.com:michaelliao/learngit.git

注意,远程库的名称叫github,不叫origin了。

接着,再关联Gitee的远程库:

git remote add gitee git@gitee.com:liaoxuefeng/learngit.git

同样注意,远程库的名称叫gitee,不叫origin

现在,我们用git remote -v查看远程库信息,可以看到两个远程库:

git remote -v
gitee	git@gitee.com:liaoxuefeng/learngit.git (fetch)
gitee	git@gitee.com:liaoxuefeng/learngit.git (push)
github	git@github.com:michaelliao/learngit.git (fetch)
github	git@github.com:michaelliao/learngit.git (push)

如果要推送到GitHub,使用命令:

git push github master

如果要推送到Gitee,使用命令:

git push gitee master

这样一来,我们的本地库就可以同时与多个远程库互相同步:

Gitee也同样提供了Pull request功能,可以让其他小伙伴参与到开源项目中来。

👉自定义Git

参考链接:自定义Git - Git教程 - 廖雪峰的官方网站

1、忽略特殊文件

你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件等等,每次git status都会显示Untracked files ...。

这个问题解决方案如下:

在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。

  • 注意:.gitignore文件本身应该提交给Git管理,这样可以确保所有人在同一项目下都使用相同的.gitignore文件。

无需从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:GitHub/gitignore

忽略文件的原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

2、配置别名

举个例子:

git config --global alias.st status         用st就表示status

git config --global alias.co checkout   用co表示checkout

git config --global alias.ci commit       用ci表示commitbr表示branch

git config --global alias.br branch  用br表示branch

lg配置成:

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

来看看git lg的效果:

配置文件

配置Git的时候,加上--global是针对当前用户起作用的,

如果不加,那只针对当前的仓库起作用。

每个仓库的Git配置文件都放在.git/config文件中:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = git@github.com:michaelliao/learngit.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[alias]
    last = log -1

别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。

而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中:

$ cat .gitconfig
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status
[user]
    name = Your Name
    email = your@email.com

配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置,或者直接删掉配置文件错误的那一行。

  • 总结

给Git配置好别名,就可以输入命令时偷个懒。

3、搭建Git服务器

GitHub就是一个免费托管开源代码的远程仓库。

但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,因此选择自己搭建一台Git服务器作为私有仓库使用。

搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

👉 Git Submodule(子模块)

  • Submodule = 在一个 Git 仓库里,嵌入另一个独立的 Git 仓库。
  • 存在共用算法库、第三方库时,用于管理依赖的独立仓库。
  • 使用场景:
    GalvanoCalibration/          ← 主仓库
    ├── src/                    ← 主项目代码
    ├── CameraCalibrationLib/    ← Submodule(独立的 Git 仓库)
    ├── ImageProcessingLib/      ← Submodule(独立的 Git 仓库)
    └── .gitmodules              ← 记录子模块的配置
    • 每个子模块:
      • 有自己的 .git 目录(独立仓库)
      • 有自己的提交历史
      • 主仓库只记录:“我用的是子模块的哪个 commit”

常用操作

1、添加子模块:

git submodule add https://github.com/xxx/CameraCalibrationLib.git

会在当前目录创建一个 CameraCalibrationLib/ 文件夹,并生成 .gitmodules

2、克隆带子模块的项目:

git clone https://github.com/xxx/GalvanoCalibration.git
cd GalvanoCalibration
git submodule init      # 初始化子模块配置
git submodule update    # 拉取子模块代码

或者一步到位:

git clone --recursive https://github.com/xxx/GalvanoCalibration.git

3、更新子模块到最新:

cd CameraCalibrationLib
git pull origin main
cd ..
git add CameraCalibrationLib
git commit -m "chore: 更新相机标定库到最新版本"
git push

4、在主项目里改子模块代码:

  1. 进入子模块目录 → 切分支 → 改代码 → commit → push
  2. 回到主项目 → git add 子模块名 → commit → push
  3. 这样主项目就记录了“子模块用了新版本”

⚠️ Submodule 的坑(新手必看)

怎么避

克隆后子模块是空的

记得 git submodule update --init --recursive

子模块停在“游离 HEAD”状态

进入子模块后 git checkout main(或你的分支)

别人更新了子模块版本,你 pull 后代码没变

执行 git submodule update 同步

删除子模块很麻烦

用工具或手动删 .gitmodules + .git/config + 缓存

拓展

1、git的命名窗口关闭之后,继续使用之前创建的仓库

无需重新创建。

在你创建仓库文件夹内鼠标右键有个 Git Bash Here打开就好,

或者按住shift加鼠标右键有个 `在此处打开Powershell窗口`,都可以直接 使用git命令。

2、撤回或修改上一次 commit 时的错误注释

方法 1:修改最近一次提交的注释(--amend

若只是修改最近一次提交的注释(且尚未推送到远程仓库),想直接指定新注释(不打开编辑器),可以加 -m 参数:

git commit --amend -m "新的提交注释"
注意
  • 此操作会修改提交的哈希值(因为提交内容变了),所以若已推送到远程仓库,需要强制推送(git push --force),但慎用强制推送(可能影响协作)。

方法 2:撤销上一次提交(保留更改)

如果想完全撤销上一次提交(但保留代码更改),可以:

git reset --soft HEAD~1
  • 这会撤销提交,但更改仍保留在暂存区(staging area),你可以重新提交并修改注释:
git commit -m "新的提交注释"
参数说明
  • --soft:保留更改并保留暂存区内容
  • --mixed(默认):保留更改但取消暂存(需重新 git add
  • --hard:彻底丢弃更改(慎用!)

总结

场景命令
修改最近一次提交的注释git commit --amend -m "新注释"
撤销最近一次提交(保留更改)git reset --soft HEAD~1 + 重新提交
修改历史提交的注释git rebase -i HEAD~N + 标记 reword
已推送提交的补救谨慎使用 git push --force 或新建修正提交
最佳实践
  • 若提交未推送,优先用 git commit --amend

3、.gitignore中已添加,但是下次推送时GitHub Desktop还会显示且可勾选一起推送某文件

现象:

  • 已在 .gitignore 中添加了某个文件夹,但下次在 GitHub Desktop 中推送时,那个文件夹里的文件仍然显示在 Changes 中可以被勾选推送。
  • 这说明那些文件已经被 Git 追踪(tracked)了,所以 .gitignore 对它们不起作用——.gitignore 只忽略未被追踪的文件

解决方法:

1、假设要忽略的文件夹叫 bigfolder

git rm -r --cached bigfolder

2、然后提交这次"移除追踪"的动作:

git commit -m "Remove bigfolder from tracking, let .gitignore take over"
  • --cached= 只动 Git 的索引记录,你磁盘上的文件原封不动。

3、回去 GitHub Desktop 点 Push ,会发现:

bigfolder/里的文件 从 Changes 里消失了
.gitignore已经生效(因为它现在变成了 untracked + ignore 匹配)
下次再改那些文件,也不会再冒出来了

本人实操:

git rm -r --cached E:/projec/振镜拼接/ImageProcessing/ImageProcessing/x64
git rm -r --cached E:/projec/振镜拼接/ImageProcessing/.vs
git commit -m "删除.vs和ImageProcessing/x64这两个路径的追踪"
over

4、本地仓库重新绑定到新的远程仓库:修改 Git 的 remote地址

一、准备工作

  1. 打开命令行:在 GitHub Desktop 中,点击菜单栏的 Repository-> Open in Command Prompt(Windows)或 Open in Terminal(Mac/Linux)。

  2. 确认当前状态:先查看一下现在绑定的地址,确认是否需要修改:

    git remote -v

二、重新绑定新远程仓库

你可以选择以下任意一种方式来重新绑定:

方式一:直接修改现有地址(推荐)

这种方式最快捷,直接把现有的 origin地址替换成你的新地址:

  • git remote set-url origin http://xt_xlchen@192.168.1.220:10101/r/GalvanoCalibration.git

方式二:先删除再重新添加

如果你想更彻底地清理旧关联,可以先删掉现有的 origin,再重新关联:

  • git remote remove origin
  • git remote add origin http://xt_xlchen@192.168.1.220:10101/r/GalvanoCalibration.git

5、分支1还有在修改内容时,将分支2的最新提交融过去。

后把一个本地提交合入另一分支:

# 进入目标项目目录:要接收提交的 0814优化精度 分支所在目录
cd E:\git\目标项目目录

# 确认当前确实处于目标分支,应显示:0814优化精度
git branch --show-current

# 查看目标分支已有的未提交修改,避免误覆盖正在开发的内容
git status --short

# 仅列出已修改的文件名,用于与待合入提交的文件对照是否重叠
git diff --name-only

# 查看来源提交会修改哪些文件、改动量和提交说明
# 623e414 是 tree排查链路 中的来源提交号
git show --stat 623e414

# 将来源提交复制并应用到当前 0814优化精度 分支
# 此操作只在本地创建提交,不会推送远程
git cherry-pick 623e414

# 查看最新一条提交,确认 cherry-pick 已成功
git log -1 --oneline

cherry-pick 提示冲突,先手动处理冲突文件,再执行:

# 标记冲突已处理
git add <冲突文件路径>

# 继续完成本次合入
git cherry-pick --continue

若决定放弃本次合入:

# 恢复到执行 cherry-pick 前的状态
git cherry-pick --abort

【问题解决】git log后一直出现:(冒号)

参考链接:git log 后一直出现:(冒号)的原因以及处理方法_git log 冒号怎么搜索-CSDN博客

原因:

运用 git commit 命令提交信息数量增多,且你当前窗口没有铺满全屏

解决方案:
  1. 窗口铺满全屏则不会出现此问题
  2. 上下方向键或者鼠标滑轮查看更多未展现的提交信息
  3. 按 qQZZ 直接退出该查看模式

【问题解决】git查看差异显示END后的退出方法

原因:

在 Git 中查看差异(如使用 git diff 或 git show)时,若输出内容较多,Git 会调用分页器(如 less)来分页显示内容。当看到 END 提示时,表示已到达输出末尾,此时可以通过以下方式退出:

(退出分页器的方法)

  • 按 q 键:直接退出分页器,返回终端。
  • 按 Ctrl + C:强制退出(不推荐,可能中断其他进程)

其他分页器快捷键(less 常用操作)

  • 空格:向下翻一页。
  • b:向上翻一页。
  • /:搜索内容(如 /keyword),按 n 跳转到下一个匹配项。
  • q:退出。

【问题解决】报错:ssh: connect to host github.com port 22: Connection refused

在克隆远程库时遇到这个报错。

克隆远程库时,明明

格式1:https://github.com/michaelliao/gitskills.git 

格式2:git clone git@github.com:michaelliao/gitskills.git 

以上两种格式皆可。

但在使用格式1时,出现了报错如下:

解决方法就是换成格式2即可。

报错原因:

ssh: connect to host github.com port 22: Connection refused这个错误提示的是连接github.com的22端口被拒绝了。

22端口可能被防火墙屏蔽了,可以尝试连接GitHub的443端口。

【问题解决】warning: LF will be replaced by CRLF the next time Git touches it

现象:

git add --all 后出现警告warning: in the working copy of 'NEU-DET/ANNOTATIONS/crazing_1.xml', LF will be replaced by CRLF the next time Git touches it

参考链接:git提示“warning: LF will be replaced by CRLF”的解决办法-CSDN博客

解决方案:(我使用情况一已解决)

  • 情况一:

Git 可以在你提交时自动地把回车(CR)和换行(LF)转换成换行(LF),而在检出代码时把换行(LF)转换成回车(CR)和换行(LF)。

可以用 git config --global core.autocrlf true 来打开此项功能。

如果是在 Windows 系统上,把它设置成 true,这样在检出代码时,换行会被转换成回车和换行:

#提交时转换为LF,检出时转换为CRLF
$ git config --global core.autocrlf true
  • 情况二:

如果使用以换行(LF)作为行结束符的 Linux 或 Mac,你不需要 Git 在检出文件时进行自动的转换。然而当一个以回车(CR)和换行(LF)作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 所以,你可以把 core.autocrlf 设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换:(这样在 Windows 上的检出文件中会保留回车和换行,而在 Mac 和 Linux 上,以及版本库中会保留换行。)

#提交时转换为LF,检出时不转换
$ git config --global core.autocrlf input
  • 情况三:

如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 false 取消此功能,把回车保留在版本库中:

#提交检出均不转换
$ git config --global core.autocrlf false

你也可以在文件提交时进行safecrlf检查

#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true   
 
#允许提交包含混合换行符的文件
git config --global core.safecrlf false   
 
#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

通俗解释

  • git 的 Windows 客户端基本都会默认设置 core.autocrlf=true,设置core.autocrlf=true, 只要保持工作区都是纯 CRLF 文件,编辑器用 CRLF 换行,就不会出现警告了;
  • Linux 最好不要设置 core.autocrlf,因为这个配置算是为 Windows 平台定制;
  • Windows 上设置 core.autocrlf=false,仓库里也没有配置 .gitattributes,很容易引入 CRLF 或者混合换行符(Mixed Line Endings,一个文件里既有 LF 又有CRLF)到版本库,这样就可能产生各种奇怪的问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值