Git从入门到精通

Git 是什么?

不要把 Git 当作一个枯燥的"版本控制工具",请把它想象成:

  1. 时光机:你可以随时回到代码的过去(昨天、上个月、甚至一年前的状态)。

  2. 平行宇宙(分支):你可以同时开发"新功能"和"修复Bug",互不干扰,最后合并。

  3. 后悔药:删错文件了?改乱代码了?一个命令就能还原。

一、Git 核心概念

在学用法前,先吃透 Git 的核心设计,能避免后续操作踩坑:

概念 通俗解释
工作区 你电脑上实际写代码的文件夹(能看到、能修改的文件都在这里)
暂存区(索引) 临时存放待提交的修改,是 "工作区" 和 "本地仓库" 的中间层(通过 git add 填充)
本地仓库 本地的版本数据库,保存所有 commit 记录(版本快照),.git 文件夹就是仓库
远程仓库 云端的仓库(如 GitHub/GitLab/Gitee),用于多人协作同步代码
commit 版本快照,是 Git 最小的可追溯单元(包含修改内容、作者、时间、备注)
分支(branch) 独立的开发线,比如 main(主分支)、dev(开发分支)、feature(功能分支)
HEAD 指针,指向当前所在的分支 / 版本(可以理解为 "你现在的位置")
哈希值(SHA-1) 每个 commit 唯一的 ID(40 位字符,通常用前 7 位即可)
  1. 修改(Modified)和新建(New)的文件都需要 git add。

  2. 区别在于: "未追踪"是 Git 根本不认识 的文件;"未暂存"是 Git 认识但觉得你还没改好的文件。

二、Git 基础操作

初始化 / 克隆仓库

初始化本地仓库(从零创建项目):

bash 复制代码
# 进入项目文件夹
cd your-project-folder
# 初始化 Git 仓库
git init

(此时文件夹下会多出一个隐藏的 .git 文件夹,千万别删)

克隆远程仓库(复制已有项目):

bash 复制代码
# 克隆 HTTPS 地址(无需配置密钥)
git clone https://github.com/xxx/xxx.git
# 克隆 SSH 地址(需配置密钥,更安全)
git clone git@github.com:xxx/xxx.git

第一次安装后的自报家门

Git 需要知道是谁在提交代码,否则以后出了 Bug 找不到背锅侠。

bash 复制代码
# 全局配置(设置一次即可)
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"

# 查看配置
git config --list

基础提交流程(工作区 → 暂存区 → 本地仓库)

这是你每天要敲几十遍的命令组合。

1. 查看状态 (最重要!)

不知道现在发生了什么?随时敲这个命令。

复制代码
git status
  • 红色文件:被修改了,还在工作区

  • 绿色文件:已经 add 了,在暂存区,等待提交。

2. 添加到暂存区 (add)

bash 复制代码
git add .           # 把当前目录下所有修改放入暂存区(最常用)
git add main.cpp    # 只把 main.cpp 放入暂存区
git add -u          # 只添加已跟踪文件的修改(不包含新增文件)

3. 提交存档 (commit)

这会生成一个版本快照。必须写备注!

复制代码
git commit -m "修复了坦克血条不显示的Bug"

4. 查看历史 (log)

复制代码
git log             # 查看详细历史(作者、时间、哈希值)
git log --oneline   # 简洁模式(只看版本号和备注)

5. 关联远程仓库 (remote)

bash 复制代码
# 关联远程仓库(首次推送时需要)
git remote add origin 远程仓库地址  # origin 是远程仓库的默认别名
# 查看已关联的远程仓库
git remote -v

分支管理 (Branching) ------ 进阶核心

分支是 Git 的杀手锏。想象一下,你正在开发"坦克开火"功能,突然老板让你修一个"菜单打不开"的 Bug。

你不需要回退代码,只需要切一个分支。

1. 分支操作

bash 复制代码
# 查看所有分支(* 表示当前分支)
git branch            # 本地分支
git branch -r         # 远程分支
git branch -a         # 所有分支(本地+远程)

# 创建分支
git branch dev        # 创建 dev 分支(仅创建,不切换)
git checkout -b dev   # 创建并切换到 dev 分支(常用)
git switch -c dev     # Git 2.23+ 新增,等价于 checkout -b

# 切换分支
git checkout main     # 切换到 main 分支
git switch main       # Git 2.23+ 新增,更直观

# 拉取远程新分支到本地
git checkout -b dev origin/dev  # 跟踪远程 dev 分支


2. 合并分支 (Merge)

假设你在 feature-fire 分支上开发完了,要把它合并回 main 主分支。

  1. 先切回主分支:

    复制代码
    git checkout main
  2. 执行合并:

    bash 复制代码
    # 合并 dev 到当前分支
    git merge dev
  3. 删除分支:

    bash 复制代码
    git branch -d dev     # 删除本地 dev 分支(已合并的分支)
    git branch -D dev     # 强制删除本地 dev 分支(未合并也能删)
    git push origin --delete dev  # 删除远程 dev 分支

3. 解决冲突 (Conflict)

这是新手最怕的环节。

当两个人(或者两个分支)同时修改了同一个文件的同一行代码时,Git 无法决定保留谁的,就会报错 CONFLICT。

解决步骤:

  1. 打开报错的文件。

  2. 你会看到类似这样的符号:

    复制代码
    <<<<<<< HEAD
    Health = 100;  // 你的代码
    =======
    Health = 200;  // 别人的代码
    >>>>>>> feature-fire
  3. 人工决定:删掉 <<<, ===, >>> 这些符号,保留你想要的代码(比如保留 100,或者改成 150)。

  4. 保存文件。

  5. 再次执行 git add . 和 git commit。

远程协作 (Remote)

1. 关联远程仓库

如果你是本地 git init 的,需要告诉 Git 远程地址在哪里。

复制代码
git remote add origin https://github.com/你的账号/你的仓库.git
# origin 是给远程地址起的别名,行业惯例
2. 推送 (Push)

把本地的存档上传。

复制代码
git push -u origin main
# -u 的意思是把本地 main 和远程 main 绑定,下次直接 git push 就行
3. 拉取 (Pull)

上班第一件事,先把同事写的代码拉下来。

复制代码
git pull

撤销操作

  1. 工作区 = 红色 (git status 显示的颜色) = 还没 add

  2. 暂存区 = 绿色 (git status 显示的颜色) = add 了,但还没 commit

撤销工作区的修改

(我刚写的代码写烂了,还没add, 想回到之前的状态):

bash 复制代码
git checkout -- filename  # 恢复文件到最近一次 commit 状态
# 或者新版命令
git restore filename

撤销暂存区的修改

(我手滑 add 了,想拿出来):

复制代码
git reset HEAD filename
# 或者新版命令
git restore --staged filename

版本回退

(彻底回退到上一个版本,慎用):

bash 复制代码
git reset --hard HEAD^    # 回退到上一个版本

# 本地回滚(保留修改)
git reset --soft 哈希值      # 回滚 commit,保留工作区/暂存区

# 本地回滚(清空修改,谨慎)
git reset --hard 哈希值      # 彻底回到指定版本,删除所有未提交修改

# 远程回滚(安全方式,推荐)
git revert 哈希值            # 新增反向 commit,抵消指定版本的修改
git push origin main

临时保存手头工作

(我要去修Bug,但现在代码还没写完,不想 commit):

bash 复制代码
# 暂存当前工作区修改
git stash save "暂存登录功能的未完成修改"

git stash #系统自动贴个默认标签(通常是你上一次 commit 的名字)

# 查看所有暂存记录
git stash list

# 恢复最近一次暂存(保留暂存记录)
git stash apply stash@{0}  # stash@{0} 是第一条暂存记录,可省略
# 恢复并删除暂存记录(常用)
git stash pop

# 删除指定暂存记录
git stash drop stash@{0}
# 删除所有暂存记录
git stash clear

标签管理(标记重要版本,如发布版本)

bash 复制代码
# 创建标签(打标签,比如 v1.0 发布版本)
git tag v1.0  # 轻量标签(仅标记)
git tag -a v1.0 -m "v1.0 正式发布"  # 附注标签(包含备注、作者,推荐)

# 查看所有标签
git tag

# 推送标签到远程
git push origin v1.0        # 推送单个标签
git push origin --tags      # 推送所有标签

# 删除标签
git tag -d v1.0             # 删除本地标签
git push origin --delete v1.0  # 删除远程标签

三、Git 核心特性

1. 分布式版本控制(核心优势)

  • 本地完整保留所有版本记录,无需联网即可提交、查看历史、切换分支;
  • 即使远程仓库宕机,本地仓库仍能正常工作,恢复后同步即可;
  • 多人协作时,可先本地提交,再统一推送到远程,减少冲突概率。

2. 快照式存储(而非增量存储)

  • SVN 等工具是 "增量存储"(只记录每次修改的差异),Git 是 "快照存储"(每次 commit 保存整个项目的完整快照);
  • 优势:回溯版本、对比差异时速度更快,且能完整恢复任意版本的所有文件。

3. 分支轻量且高效

  • Git 的分支本质是 "指向 commit 的指针",创建 / 切换 / 合并分支几乎瞬间完成;
  • 支持 "特性分支工作流":一个分支开发一个功能,完成后合并到主分支,避免代码混乱。

4. 数据完整性(哈希校验)

  • 所有文件、commit、分支等都通过 SHA-1 哈希值校验,确保数据不被篡改;
  • 只要哈希值不变,版本内容就绝对完整,避免传输 / 存储过程中出现数据损坏。

5. 灵活的撤销 / 回溯机制

  • 支持多种撤销方式(checkout/reset/revert/stash),适配不同场景;
  • revert 保留历史记录,适合团队协作;reset 适合本地调整,兼顾灵活性和安全性。

6. 离线工作能力

  • 所有核心操作(commit/branch/log/stash)都可离线完成,仅 push/pull 需要联网;
  • 适合通勤、出差等无网络场景下的开发。

四、Git 常用工作流

  1. 单人开发main 分支直接开发 → commitpush
  2. 多人协作
    • 主分支 main(仅存放稳定代码);
    • 开发分支 dev(日常开发);
    • 功能分支 feature/xxx(每个功能一个分支,完成后合并到 dev);
    • 修复分支 bugfix/xxx(修复线上 bug,合并到 maindev)。

五、Git 实战案例

案例1:

分支是 Git 的杀手锏。想象一下,你正在开发"坦克开火"功能,突然老板让你修一个"菜单打不开"的 Bug。

你不需要回退代码,只需要切一个分支。

但是我目前这个分支功能还没开发好, 假设会影响到项目的运行, 那我也没办法在现在这个节点开一个分支, 我依然需要开发完这个功能或者直接回退吗?

解决方案1:

你的顾虑是对的:如果你现在的代码写了一半,全是报错,这时候直接开一个新分支,新分支里也会全是报错。在那堆烂代码的基础上修 Bug,简直是灾难。

但 Git 早就料到了这种情况。你不需要 开发完,也不需要把代码删掉回退。

解决这个问题有两个核心思路,我为你推荐最经典的一个:"时空冻结大法"(git stash)

核心逻辑转变

首先纠正一个概念:当你去修"菜单Bug"时,你不是基于你现在"写烂了的坦克代码"去修,而是要基于**"昨天那个正常的版本(Main/master分支)"**去修。

所以流程是:

  1. 把手头写烂的代码**"冻结"**起来(藏到一个临时抽屉里)。

  2. 你的工作区瞬间变干净,回到上次提交的状态。

  3. 切回 Main 分支(它是干净的)。

  4. 基于 Main 开一个 Fix-Menu 分支去修 Bug。

  5. 修完回来,把冻结的代码**"解冻"**,继续写。

使用 git stash

假设你现在在 feature-tank 分支,代码写了一半,编译报错中。

第一步:冻结现场

输入这个命令:

复制代码
git stash

发生了什么?

你会发现你刚才写的那堆乱七八糟的代码凭空消失了 !你的文件变回了上次 commit 时的干净模样,项目又可以运行了。

别慌,代码没丢,是被 Git 存到一个特殊的"堆栈"里了。

第二步:切换回主基地

现在你的工作区是干净的,可以安全切回主分支了:

复制代码
git checkout main
第三步:去修 Bug

基于干净的主分支,创建一个修 Bug 的分支:

复制代码
git checkout -b fix-menu

然后你去改代码,修好bug,提交:

bash 复制代码
git add .
git commit -m "修好了菜单Bug"

最后合并回主分支(这一步看你们团队流程,如果是个人开发就直接合):

复制代码
git checkout main
git merge fix-menu
第四步:回到战场(解冻)

Bug 修完了,你要回去继续写你的坦克。

先切回你的开发分支:

复制代码
git checkout feature-tank

然后输入"解冻"命令:

复制代码
git stash pop

发生了什么?

砰!你之前写了一半的、报错的那堆代码又回来了 ,进度条完美衔接。你可以继续接着写,就像中间没被打断过一样。

而且:

解冻出来的,完全是你原来那一堆"写了一半、报错"的旧代码。

而且,那个菜单 Bug 在你当前的这个分支里,依然没有被修复。

那我想要那个修复的 Bug 怎么办?

既然你在主分支(Main)已经修好了 Bug,你肯定希望你的开发分支(Feature-Tank)也能享受到这个修复,对吧?

你需要做一个动作:"同步"(Merge 或 Rebase)

正确的操作流程:
  1. 解冻代码

    复制代码
    git stash pop
    # 你的烂代码回来了
  2. 先把你手头的烂代码提交了(WIP 提交法):

    复制代码
    git add .
    git commit -m "WIP: 坦克写了一半,先存一下,准备合并主分支修复"
    • 因为如果不提交,Git 可能不准你合并别的分支,怕覆盖你的修改。
  3. 把主分支的修复"吸"过来

    复制代码
    # 确保我在 feature-tank 分支
    git merge main

这句话的意思是:"Git,请把 Main 分支里最新的改动(包括那个修复的菜单 Bug),合并到我当前的分支里来。"

这只是 Git 自动打开了一个叫 Vim 的文本编辑器,让你确认或修改这次合并的"提交备注"(Commit Message)。

因为你正在把主分支的代码合并进子分支,Git 需要生成一个新的**"合并节点"(Merge Commit)**来记录这件事,而每一个 Commit 都必须有备注,所以它弹出来问你:"默认备注是这个,你要改吗?"

🚀 怎么退出去?(最重要的一步)

你需要按以下步骤操作(请确保输入法是英文模式):

  1. 按一下键盘左上角的 Esc 键(确保退出了编辑模式)。

  2. 输入Shfit+冒号 :(你会看到屏幕最左下角出现了一个冒号)。

  3. 输入字母 wq(w 意思是 Write/保存,q 意思是 Quit/退出)。

  4. 按回车键 Enter

大功告成

现在,你的代码里既有你写了一半的坦克功能,也拥有了修好的菜单。

补充一个情况:如果我一开始不在分支怎么办?我的写一半的代码不是在分支里写的, 而是直接在main主分支写的;

不用担心,这种情况非常常见!这就是所谓的**"哎呀,我忘切分支了"**事故。

首先告诉你一个事实:即使你觉得自己没开分支,你其实也在分支上。

通常情况下,你默认就在 main (或 master) 分支上。

这反而更危险!因为 main 分支应该是最干净、随时能运行的版本,结果你现在把烂代码直接写在 main 上了。

但别怕,Git 的 stash 有一个隐藏的神奇功能它可以把"冻结"的代码,"解冻"到另一个全新的分支去!

我们可以利用这个特性,把你写错位置的代码,"乾坤大挪移" 到它该去的地方。

拯救流程:把烂代码从 Main 上移走

假设场景:

  1. 你一直待在 main 分支(虽然你可能没意识到)。

  2. 你在 main 上写了一半的坦克代码,全是报错。

  3. 你需要修菜单 Bug。

第一步:冻结现场 (在 main 上)

虽然你在 main 上,但没关系,直接冻结:

复制代码
git stash

发生了什么?

  • 你的 main 分支瞬间变得干干净净(回到了上次提交的状态)。

  • 你写了一半的坦克代码被藏进抽屉了。

第二步:去修 Bug (在 main 上操作)

现在 main 是干净的了,你可以按照标准流程修 Bug:

复制代码
# 1. 为了安全,还是开个分支修 Bug 吧
git checkout -b fix-menu

# 2. ...修代码...
git add .
git commit -m "修好菜单"

# 3. 回到 main 合并
git checkout main
git merge fix-menu

此时,你的 main 分支是最新的、修好 Bug 的、且能正常运行的

第三步:关键来了!创建这一半代码原本该去的分支

你这时候不能直接解冻, 因为之前写的代码是在main上的, 解冻会把你的原来的bug代码也释放在main分支, 那就麻烦了, 我后续会详细解释;

你之前那堆坦克代码不应该在 main 上,它应该在 feature-tank 上。

所以,现在我们来创建这个迟到的分支:

bash 复制代码
# 基于最新的 main,创建并前往一个新分支
git checkout -b feature-tank
第四步:解冻 (移花接木)

现在你已经站在了 feature-tank 分支上,这时候把刚才在 main 上冻结的代码拿出来:

复制代码
git stash pop

发生了什么?

  • Git 把你刚才在 main 上写的、冻结的那堆代码,释放到了现在的 feature-tank 分支上

  • 完美结局:你的 main 分支保持了干净(只包含 Bug 修复),而你写了一半的烂代码成功转移到了 feature-tank 分支,你可以继续安心写了。

总结:Git 的一个重要特性

未提交的修改(工作区/暂存区),是不绑定分支的。

这意味着:

  1. 你在 A 分支写了行代码(没 commit)。

  2. 你 stash 存起来。

  3. 你切到 B 分支。

  4. 你 stash pop。

  5. 这行代码就跑到 B 分支来了。

所以,如果你发现自己忘切分支,直接在 main 上写了代码,通用的补救公式是:

  1. git stash (先藏起来,把 main 弄干净)

  2. git checkout -b new-branch (去建立你本该建立的分支)

  3. git stash pop (把藏起来的代码吐到这个新分支里)

搞定!就像你一开始就写对了分支一样。

如果第三步我不创建分支, 我直接git stash pop, 会不会导致我辛苦修的bug被解冻的原来的代码覆盖?

这是一个非常好的问题!你在担心 Git 会不会像"覆盖文件"那样,简单粗暴地用旧代码替换新代码。

简短回答:
不会"覆盖"消失 ,你的 Bug 修复依然存在。

但是,你会面临两个结果:要么两份代码混在一起(主分支再次变脏) ,要么发生冲突(Conflict)

我们分两种情况来推演发生了什么:

情况一:你修 Bug 的文件,和写烂代码的文件,不是同一个

  • 烂代码(Stash里):改了 Tank.cpp。

  • 修 Bug(Main上):改了 Menu.cpp。

当你执行 git stash pop 时:

  1. Git 会把 Tank.cpp 的修改放回来。

  2. Git 完全不动 Menu.cpp(保留你修好的状态)。

结果:

你的代码里同时拥有了"写烂的坦克"和"修好的菜单"。

  • 坏消息:你的 main 分支又变脏了,又跑不起来了(因为烂代码回来了)。

  • 好消息:你辛苦修的 Bug 还在。

情况二:你修 Bug 的文件,和写烂代码的文件,是同一个!

  • 烂代码(Stash里):改了 Tank.cpp 的第 10 行。

  • 修 Bug(Main上):也改了 Tank.cpp 的第 10 行。

当你执行 git stash pop 时:

Git 会立刻尖叫停下,报出 冲突(Conflict)

它会告诉你:

"大哥,你存起来的代码说第 10 行要改成 A,但现在的代码里第 10 行已经是 B 了。我不知道听谁的,你自己看着办吧。"

结果:

  • Git 绝对不会自动覆盖你的 Bug 修复。

  • 它会把两段代码都写在文件里(用 <<<< 和 >>>> 标记),让你手动选择保留哪一个。

这里的核心风险是什么?

虽然你的 Bug 修复不会丢,但我不建议你这么做(直接在 main 上 pop)。

原因有二:

  1. 污染主分支(最重要的原因)

    • main 分支应该是神圣的、随时可以运行的。

    • 你刚修好 Bug,main 本来是绿色的(健康的)。

    • 你一 pop,烂代码回来了,main 瞬间变红了(报错了)。

    • 如果你这时候不小心手抖执行了 git push,你队友拉下来的代码就全都报错了,你会成为团队里的"罪人"。

  2. 逻辑混乱

    • Git 的设计哲学是:烂代码去分支,好代码留主干。

    • 把烂代码解冻回主干,不仅违背了这个原则,还会让你下次想修新 Bug 时,又得再 stash 一次,非常麻烦。

假如我已经手快 pop 了,怎么补救?

如果你不小心在 main 上执行了 git stash pop,发现烂代码污染了主分支,别慌!你可以原地起飞

补救招数:

即使烂代码已经到了 main 的工作区里,只要你还没 commit,你依然可以现在立刻创建分支:

bash 复制代码
# 1. 我发现我在 main 上 pop 了,这不对!
# 2. 此时烂代码在工作区里

# 3. 带着这些烂代码,直接创建一个新分支并跳过去
git checkout -b feature-tank

# 4. 现在烂代码跟着你来到了 feature-tank 分支
# 5. 提交它们
git add .
git commit -m "WIP: 坦克代码"

发生了什么?

Git 允许你带着"未提交的修改"切换/创建分支。

所以,你其实是把这堆烂代码,从 main 上"驮"到了 feature-tank 上 ,然后才提交。

这样,你的 main 分支依然保持着"修好Bug"的干净状态,而烂代码也安全地落到了新分支里。

总结

  • git stash pop 是合并,不是覆盖

  • 它会把旧代码和新修复混合在一起。

  • 但这会让你的主分支变脏。

  • 最佳策略:Pop 之前,务必先切到一个新分支 (git checkout -b new-branch),把垃圾倒在垃圾桶里,不要倒在客厅地板上。

案例2:

创建分支的时候可以加注释吗?不然我怎么知道这个分支是干嘛的

直接回答你:

Git 不直接支持像 git commit -m "注释" 那样给分支加一个简单的单行注释。

Git 的设计哲学是:分支名本身就应该是注释。

但是,如果你觉得名字太短写不下,有 3 种方法 可以解决你的问题:

方法一:使用"行业标准"的分支命名法(最推荐 ⭐️)

既然分支名就是注释,那我们就把名字起得有规律、能读懂

在专业的开发团队中,我们通常使用 类型/功能描述 的格式。

常用的前缀:

  • feat/... (Feature): 开发新功能

    • 例子:feat/tank-fire (开发坦克开火功能)

    • 例子:feat/double-jump (开发二段跳)

  • fix/... (Fix): 修 Bug

    • 例子:fix/menu-crash (修复菜单崩溃)

    • 例子:fix/tank-collision (修复坦克穿模)

  • docs/... (Documentation): 只改了文档

  • refactor/... (Refactoring): 代码重构(功能没变,改了代码结构)

这样起名的好处:

当你输入 git branch 时,一目了然:

bash 复制代码
feat/tank-movement
  fix/ui-typo
* main

你一看就知道 feat/tank-movement 是干嘛的,不需要额外注释。

方法二:给分支写"描述说明书"(冷门功能)

Git 其实隐藏了一个功能,可以给分支写长篇大论的描述,但很少人知道。

  1. 切换到你想写注释的分支

  2. 输入命令:

    bash 复制代码
    git branch --edit-description
  3. 这时会弹出一个编辑器(类似你提交代码时的界面),你可以在里面随便写多少行注释都可以。写完保存退出。

怎么查看这个注释?

输入这个命令:

复制代码
git config branch.<分支名>.description
  • 缺点 :这个注释通常只保存在你的本地电脑上,推送到远程服务器(如 GitHub)时,别人是看不到的。所以这个功能比较鸡肋,只有你自己看。

方法三:利用第一条 Commit (实战技巧)

如果你觉得名字太短,描述不清,你可以在创建分支后的第一次提交里写清楚

  1. 创建分支 git checkout -b feat/complex-ai

  2. 改动一点点东西(或者创建一个空的 commit)。

  3. 提交:

    codeBash

    复制代码
    git commit --allow-empty -m "初始化:开始开发AI功能,计划包含寻路算法和攻击逻辑"
  4. 以后你查看 Log 时,第一条就很清楚这个分支的起源和目的是什么

相关推荐
stevenzqzq9 小时前
git 常用操作
大数据·git
Curvatureflight11 小时前
Git工作流最佳实践:从混乱到优雅
git
wu~97011 小时前
GitHub永不遗忘,使用git push -f来覆盖的提交依旧保留
git·github
Vermouth_0013 小时前
git clone的时候提示access denied
git
qq_4376572714 小时前
清楚本地的git并重新登录
git
jiang_changsheng14 小时前
工作流agent汇总分析 2
java·人工智能·git·python·机器学习·github·语音识别
梦梦代码精15 小时前
Gitee 年度人工智能竞赛开源项目评选揭晓!!!
开发语言·数据库·人工智能·架构·gitee·前端框架·开源
TheNextByte115 小时前
如何在PC和Android平板之间传输文件
android·gitee·电脑
顶点多余15 小时前
版本控制器-git
linux·git
夔曦15 小时前
Git工程日常下拉/上传完整流程(自用)
git