协作开发攻略:Git全面使用指南 — 第二部分 高级技巧与最佳实践
协作开发攻略:Git全面使用指南 — 第二部分 高级技巧与最佳实践
Git 是一种分布式版本控制系统,用于跟踪文件和目录的变更。它能帮助开发者有效管理代码版本,支持多人协作开发,方便代码合并与冲突解决,广泛应用于软件开发领域。
文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。
📖 引言 🔥
- 为什么选择Git?
- Git的基本概念简述
- 安装与配置Git环境
📖 第一部分 Git基础 🔥
- 版本控制概述
- 初始化仓库
- 文件状态管理
- 提交更改
- 查看历史记录
- 撤销操作
- 分支管理
- 远程仓库
- 标签管理
📖 第二部分 高级技巧与最佳实践 🔥
- 交互式重置
- 变基操作
- 子模块
- Git Hooks
- 全性和身份验证
📖 第三部分 特殊应用场景 🔥
- 大型文件存储——Git LFS 解决方案
- 协作开发流程——Git Flow/GitHub/GitLab CI/CD 集成
📖 结语 🔥
- 要点速查
- 进一步学习资源
- 常见问题解答
第二部分 高级技巧与最佳实践
10. 交互式重置
在 Git 中,交互式重置是一种强大的工具,可以帮助你重新组织提交历史或更精细地控制暂存区的内容。以下是如何使用交互式重置来重新组织提交历史和交互式地添加部分内容至暂存区的详细内容。
重新组织提交历史
git rebase -i
命令允许你交互式地修改提交历史。你可以进行多种操作,如合并提交、删除提交、重新排序提交等。
-
启动交互式 rebase:
使用git rebase -i <commit-hash>
命令可以启动交互式 rebase。<commit-hash>
是你要开始重写的最后一个提交之前的那个提交。git rebase -i HEAD~3
这条命令会打开一个文本编辑器,显示最近的三个提交(包括当前的
HEAD
)。 -
编辑提交历史:
在编辑器中,你会看到类似以下的内容:pick abc1234 (HEAD -> main) Add new feature pick def5678 Fix bug in new feature pick ghi9012 Update documentation
每一行代表一个提交,并且每行前面有一个关键字(如
pick
)。你可以对这些关键字进行修改以执行不同的操作:pick
:保留该提交。reword
:保留该提交,但允许你修改提交信息。edit
:保留该提交,但在应用该提交后暂停 rebase,允许你进一步修改提交。squash
:将该提交与其前一个提交合并。fixup
:将该提交与其前一个提交合并,但不保留该提交的提交信息。exec
:在每个提交之后运行一个 shell 命令。drop
:删除该提交。
例如,如果你想将
Fix bug in new feature
提交与Add new feature
提交合并,可以将def5678
行的pick
改为squash
:pick abc1234 (HEAD -> main) Add new feature squash def5678 Fix bug in new feature pick ghi9012 Update documentation
-
保存并退出编辑器:
保存并退出编辑器后,Git 会按照你的指示重新组织提交历史。如果选择了squash
或fixup
,Git 会要求你编辑合并后的提交信息。 -
完成 rebase:
如果一切顺利,rebase 会自动完成。如果有冲突,你需要手动解决冲突,然后继续 rebase:git rebase --continue
实战示例
假设你在 main
分支上进行了几次提交,现在希望将这些提交重新组织。
-
查看当前提交历史:
git log --oneline
输出可能如下:
ghi9012 (HEAD -> main) Update documentation def5678 Fix bug in new feature abc1234 Add new feature
-
启动交互式 rebase:
git rebase -i HEAD~3
-
编辑提交历史:
在编辑器中,将def5678
的pick
改为squash
:pick abc1234 Add new feature squash def5678 Fix bug in new feature pick ghi9012 Update documentation
-
保存并退出编辑器:
保存并退出编辑器后,Git 会要求你编辑合并后的提交信息:# This is a combination of 2 commits. # The first commit's message is: Add new feature# This is the 2nd commit message:Fix bug in new feature# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch main # Your branch is up to date with 'origin/main'. # # Changes to be committed: # modified: src/feature.py #
你可以编辑这个信息,然后保存并退出编辑器。
-
完成 rebase:
git rebase --continue
交互式地添加部分内容至暂存区
git add -p
命令允许你交互式地选择要添加到暂存区的部分更改。这对于更精细地控制提交内容非常有用。
-
查看当前状态:
使用git status
命令查看当前工作区的状态。git status
输出可能如下:
On branch main Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)modified: src/main.pymodified: README.md
-
交互式地添加部分内容至暂存区:
使用git add -p
命令启动交互式添加。git add -p
-
选择要添加的更改:
Git 会逐个显示文件中的更改块,并提示你选择要添加到暂存区的更改。选项包括:y
:添加该更改块。n
:不添加该更改块。a
:添加所有剩余的更改块。d
:不添加任何剩余的更改块。q
:退出而不添加任何更改块。s
:将当前更改块分割成更小的块。e
:手动编辑当前更改块。
例如,对于
src/main.py
文件中的更改,Git 会显示:diff --git a/src/main.py b/src/main.py index 1234567..89abcde 100644 --- a/src/main.py +++ b/src/main.py @@ -10,7 +10,7 @@def main():print("Hello, World!") - print("This is a test.") + print("This is a test with some changes.")Stage this hunk [y,n,q,a,d,/,e,?]? y
-
完成添加:
继续选择其他文件中的更改,直到所有需要的更改都已添加到暂存区。 -
提交更改:
使用git commit
命令提交更改。git commit -m "Add specific changes to main.py"
实战示例
假设你在 src/main.py
和 README.md
文件中进行了多个更改,但只希望将 src/main.py
中的一部分更改提交。
-
查看当前状态:
git status
输出可能如下:
On branch main Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)modified: src/main.pymodified: README.md
-
交互式地添加部分内容至暂存区:
git add -p
-
选择要添加的更改:
diff --git a/src/main.py b/src/main.py index 1234567..89abcde 100644 --- a/src/main.py +++ b/src/main.py @@ -10,7 +10,7 @@def main():print("Hello, World!") - print("This is a test.") + print("This is a test with some changes.")Stage this hunk [y,n,q,a,d,/,e,?]? y
-
完成添加:
继续选择其他文件中的更改,直到所有需要的更改都已添加到暂存区。 -
提交更改:
git commit -m "Add specific changes to main.py"
11. 变基操作
变基(Rebase)是 Git 中一个强大的工具,用于将一个分支的更改应用到另一个分支上。与合并(Merge)不同,变基会重新应用提交历史,使得提交历史更加线性和整洁。以下是关于变基操作的详细内容,包括什么是变基、何时使用它以及如何解决变基过程中的冲突。
什么是变基?何时使用它?
变基是一种将一个分支的更改应用到另一个分支上的方法。具体来说,变基会将当前分支的提交历史“移动”到目标分支的顶部,使提交历史看起来像是在目标分支上直接进行的一样。这使得提交历史更加线性和易于理解。
何时使用变基?
- 保持提交历史的线性:变基可以使提交历史更加线性和简洁,特别适合于特性分支和小团队。
- 清理提交历史:通过交互式变基,可以删除不必要的提交或合并多个提交,使提交历史更清晰。
- 协作开发:在多人协作开发时,变基可以帮助你保持本地分支与远程分支同步,避免频繁的合并提交。
- 简化 Pull Request:在向主分支提交 Pull Request 之前,使用变基可以使提交历史更干净,便于代码审查。
基本用法
-
普通变基:
使用git rebase <target-branch>
命令将当前分支的更改应用到目标分支上。git rebase main
-
交互式变基:
使用git rebase -i <target-commit>
命令启动交互式变基,允许你修改提交历史。git rebase -i HEAD~3
解决变基过程中的冲突
在变基过程中,如果目标分支上有新的提交,可能会导致冲突。以下是解决这些冲突的步骤:
-
开始变基:
使用git rebase <target-branch>
命令开始变基。git rebase main
-
识别冲突:
如果变基过程中出现冲突,Git 会暂停并提示哪些文件存在冲突。error: could not apply abc1234... Add new feature hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git rebase --continue'
-
解决冲突:
打开冲突文件,手动解决冲突。冲突标记与合并冲突类似:<<<<<<< HEAD def main():print("Hello, World!") ======= def main():print("Hello, Git!") >>>>>>> feature-branch
根据实际需求编辑文件,选择保留或合并冲突部分。例如:
def main():print("Hello, World and Git!")
-
添加解决冲突后的文件到暂存区:
使用git add
命令将解决冲突后的文件添加到暂存区。git add src/main.py
-
继续变基:
使用git rebase --continue
命令继续变基过程。git rebase --continue
-
放弃变基:
如果你在变基过程中遇到了难以解决的问题,可以使用git rebase --abort
命令放弃变基,回到变基前的状态。git rebase --abort
实战示例
假设你在 feature-branch
上进行了开发,并希望将其变基到 main
分支上。
-
切换到
feature-branch
:git checkout feature-branch
-
开始变基:
git rebase main
输出可能如下:
First, rewinding head to replay your work on top of it... Applying: Add new feature Using index info to reconstruct a base tree... M src/main.py Falling back to patching base and 3-way merge... Auto-merging src/main.py CONFLICT (content): Merge conflict in src/main.py error: could not apply abc1234... Add new feature hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git rebase --continue'
-
解决冲突:
打开src/main.py
文件,解决冲突:def main():print("Hello, World and Git!")
-
添加解决冲突后的文件到暂存区:
git add src/main.py
-
继续变基:
git rebase --continue
12. 子模块
在 Git 中,子模块(Submodule)允许你将一个外部的 Git 仓库作为子目录包含在你的主项目中。这对于管理和跟踪依赖项非常有用。以下是如何包含外部项目作为子模块、更新和管理子模块的详细内容。
包含外部项目作为子模块
-
添加子模块:
使用git submodule add <repository-url> <path>
命令可以将一个外部 Git 仓库作为子模块添加到你的项目中。git submodule add https://github.com/username/external-project.git external-project
这条命令会将
external-project
仓库克隆到external-project
目录,并在.gitmodules
文件中记录子模块的信息。 -
初始化子模块:
如果你从一个已经包含子模块的仓库克隆了项目,需要初始化并更新子模块。git submodule init git submodule update
你也可以使用一条命令来同时初始化和更新子模块:
git submodule update --init --recursive
-
查看子模块状态:
使用git status
命令可以查看子模块的状态。git status
输出可能如下:
On branch main Your branch is up to date with 'origin/main'.Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)modified: external-project (new commits)no changes added to commit (use "git add" and/or "git commit -a")
-
提交子模块更改:
如果你在子模块中进行了更改并希望将其包含在主项目的提交中,首先需要在子模块中进行提交。cd external-project git add . git commit -m "Update external project" cd .. git add external-project git commit -m "Update external project submodule"
实战示例
假设你有一个主项目 myproject
,并且希望将 external-project
作为子模块包含进来。
-
添加子模块:
git submodule add https://github.com/username/external-project.git external-project
-
初始化并更新子模块:
git submodule update --init --recursive
-
查看子模块状态:
git status
-
在子模块中进行更改:
cd external-project # 在这里进行更改 git add . git commit -m "Update external project" cd ..
-
提交子模块更改到主项目:
git add external-project git commit -m "Update external project submodule"
更新和管理子模块
-
更新子模块:
使用git submodule update
命令可以更新子模块到其最新提交。git submodule update
-
更新子模块到最新远程分支:
使用git submodule update --remote
命令可以更新子模块到其远程分支的最新提交。git submodule update --remote
-
更新所有子模块:
如果你有多个子模块,可以使用--recursive
选项来递归更新所有子模块。git submodule update --init --recursive
-
删除子模块:
删除子模块需要几个步骤:- 从
.gitmodules
文件中删除子模块配置。 - 从
.git/config
文件中删除子模块配置。 - 从工作树中删除子模块文件夹。
- 移除子模块的 Git 链接。
例如,假设你要删除
external-project
子模块:# 从 .gitmodules 文件中删除子模块配置 sed -i '/\[submodule "external-project"\]/d' .gitmodules# 从 .git/config 文件中删除子模块配置 git config --remove-section submodule.external-project# 从工作树中删除子模块文件夹 rm -rf external-project# 移除子模块的 Git 链接 git rm -f external-project
最后,提交这些更改:
git commit -m "Remove external-project submodule"
- 从
-
查看子模块信息:
使用git submodule status
命令可以查看子模块的状态。git submodule status
输出可能如下:
+abc1234 external-project (heads/main)
-
同步子模块 URL:
如果你需要更改子模块的 URL,可以在.gitmodules
文件中修改相应的 URL,然后使用git submodule sync
命令同步更改。# 修改 .gitmodules 文件中的 URL [submodule "external-project"]path = external-projecturl = https://github.com/new-username/external-project.git# 同步子模块 URL git submodule sync
实战示例
假设你已经将 external-project
作为子模块包含在 myproject
中,并且现在需要更新它。
-
更新子模块:
git submodule update
-
更新子模块到最新远程分支:
git submodule update --remote
-
更新所有子模块:
git submodule update --init --recursive
-
查看子模块状态:
git submodule status
-
删除子模块:
# 从 .gitmodules 文件中删除子模块配置 sed -i '/\[submodule "external-project"\]/d' .gitmodules# 从 .git/config 文件中删除子模块配置 git config --remove-section submodule.external-project# 从工作树中删除子模块文件夹 rm -rf external-project# 移除子模块的 Git 链接 git rm -f external-project# 提交更改 git commit -m "Remove external-project submodule"
13. Git Hooks
Git 钩子(Git Hooks)是一种强大的工具,允许你在特定的 Git 事件发生时自动执行脚本。这些钩子可以帮助你自动化各种任务,如代码格式检查、测试、部署等。以下是如何使用 Git 钩子以及一些常见的应用场景。
自动执行脚本
Git 钩子分为客户端钩子和服务器端钩子。客户端钩子存储在每个仓库的 .git/hooks
目录中,而服务器端钩子存储在 Git 服务器的 hooks
目录中。以下是一些常见的钩子类型及其用途:
客户端钩子
-
pre-commit:
在git commit
命令之前运行。- 用途:代码格式检查、静态代码分析、测试等。
# .git/hooks/pre-commit #!/bin/sh echo "Running pre-commit hook..." # 运行代码格式检查 ./scripts/format-check.sh # 如果检查失败,退出并阻止提交 if [ $? -ne 0 ]; thenecho "Code format check failed. Aborting commit."exit 1 fi
-
post-commit:
在git commit
命令之后运行。- 用途:发送通知、日志记录等。
# .git/hooks/post-commit #!/bin/sh echo "Running post-commit hook..." # 发送通知 ./scripts/send-notification.sh
-
pre-rebase:
在git rebase
命令之前运行。- 用途:防止对某些分支进行变基。
# .git/hooks/pre-rebase #!/bin/sh refname=$1 if [ "$refname" = "main" ]; thenecho "Rebasing the main branch is not allowed. Aborting."exit 1 fi
-
post-merge:
在git merge
命令之后运行。- 用途:更新依赖项、生成文档等。
# .git/hooks/post-merge #!/bin/sh echo "Running post-merge hook..." # 更新依赖项 ./scripts/update-dependencies.sh
-
pre-push:
在git push
命令之前运行。- 用途:运行测试、验证代码质量等。
# .git/hooks/pre-push #!/bin/sh echo "Running pre-push hook..." # 运行测试 ./scripts/run-tests.sh # 如果测试失败,退出并阻止推送 if [ $? -ne 0 ]; thenecho "Tests failed. Aborting push."exit 1 fi
-
prepare-commit-msg:
在git commit
命令准备提交信息时运行。- 用途:自动生成提交信息、添加默认信息等。
# .git/hooks/prepare-commit-msg #!/bin/sh msg_file=$1 if [ -z "$(cat $msg_file)" ]; thenecho "Default commit message: Initial commit" > $msg_file fi
-
commit-msg:
在git commit
命令提交信息时运行。- 用途:验证提交信息格式。
# .git/hooks/commit-msg #!/bin/sh msg_file=$1 if ! grep -q "Fixes #[0-9]" $msg_file; thenecho "Commit message must include 'Fixes #<issue-number>'. Aborting commit."exit 1 fi
服务器端钩子
-
pre-receive:
在git push
命令接收到推送数据后但在更新引用前运行。- 用途:验证推送的提交、权限检查等。
# hooks/pre-receive #!/bin/sh while read oldrev newrev refname do# 检查推送的提交./scripts/check-commits.sh $oldrev $newrevif [ $? -ne 0 ]; thenecho "Push rejected: Invalid commits detected."exit 1fi done
-
post-receive:
在git push
命令更新引用后运行。- 用途:触发部署、发送通知等。
# hooks/post-receive #!/bin/sh while read oldrev newrev refname do# 触发部署./scripts/deploy.sh done
-
update:
在git push
命令更新引用前运行。- 用途:拒绝特定的推送操作。
# hooks/update #!/bin/sh refname=$1 oldrev=$2 newrev=$3 if [ "$refname" = "refs/heads/main" ]; thenecho "Pushing to main branch is not allowed. Aborting."exit 1 fi
钩子的应用场景介绍
-
代码格式检查:
使用pre-commit
钩子在每次提交前运行代码格式检查工具(如 Prettier 或 ESLint),确保代码风格一致。 -
静态代码分析:
使用pre-commit
钩子在每次提交前运行静态代码分析工具(如 SonarQube 或 PyLint),发现潜在的代码问题。 -
自动化测试:
使用pre-push
钩子在每次推送前运行自动化测试(如单元测试、集成测试),确保代码质量。 -
代码审查:
使用commit-msg
钩子在每次提交时验证提交信息,确保提交信息符合团队规范(如包含 JIRA 问题编号)。 -
依赖项管理:
使用post-merge
钩子在每次合并后更新项目的依赖项(如npm install
或pip install
),确保依赖项是最新的。 -
部署自动化:
使用post-receive
钩子在服务器端接收推送后触发自动部署(如 Docker 部署或 CI/CD 流水线),实现持续集成和持续部署。 -
权限控制:
使用pre-receive
或update
钩子在服务器端验证推送权限,确保只有授权用户可以推送更改到特定分支(如main
分支)。 -
日志记录:
使用post-commit
或post-receive
钩子在每次提交或推送后记录日志,便于审计和追踪。 -
通知系统:
使用post-commit
或post-receive
钩子在每次提交或推送后发送通知(如邮件、Slack 消息),及时通知团队成员。
实战示例
假设你希望在每次提交前运行代码格式检查,并在每次推送前运行自动化测试。
-
创建
pre-commit
钩子:# .git/hooks/pre-commit #!/bin/sh echo "Running pre-commit hook..." # 运行代码格式检查 npx prettier --check . # 如果检查失败,退出并阻止提交 if [ $? -ne 0 ]; thenecho "Code format check failed. Aborting commit."exit 1 fi
-
创建
pre-push
钩子:# .git/hooks/pre-push #!/bin/sh echo "Running pre-push hook..." # 运行测试 npm test # 如果测试失败,退出并阻止推送 if [ $? -ne 0 ]; thenecho "Tests failed. Aborting push."exit 1 fi
-
确保钩子文件具有可执行权限:
chmod +x .git/hooks/pre-commit chmod +x .git/hooks/pre-push
14. 安全性和身份验证
在 Git 中,安全性和身份验证是非常重要的方面。使用 SSH 密钥进行身份验证可以提高安全性,而设置 GPG 签名则可以确保提交的真实性。以下是如何使用 SSH 密钥进行身份验证以及如何设置 GPG 签名的详细内容。
使用 SSH 密钥进行身份验证
SSH 密钥是一种非对称加密技术,允许你以更安全的方式进行身份验证。以下是生成和配置 SSH 密钥的步骤:
-
生成 SSH 密钥:
使用ssh-keygen
命令生成 SSH 密钥对。ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
按照提示操作,通常会生成两个文件:
id_rsa
(私钥)和id_rsa.pub
(公钥)。 -
添加 SSH 密钥到 SSH 代理:
启动 SSH 代理并添加私钥。eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
-
将公钥添加到你的 Git 托管服务:
- GitHub:
- 登录 GitHub。
- 进入 Settings -> SSH and GPG keys。
- 点击 “New SSH key”,粘贴你的公钥内容(从
~/.ssh/id_rsa.pub
文件中复制),然后保存。
- GitLab:
- 登录 GitLab。
- 进入 Settings -> SSH Keys。
- 粘贴你的公钥内容(从
~/.ssh/id_rsa.pub
文件中复制),然后保存。
- Bitbucket:
- 登录 Bitbucket。
- 进入 Personal settings -> SSH keys。
- 粘贴你的公钥内容(从
~/.ssh/id_rsa.pub
文件中复制),然后保存。
- GitHub:
-
测试 SSH 连接:
使用ssh -T git@github.com
或ssh -T git@gitlab.com
命令测试 SSH 连接是否成功。ssh -T git@github.com
如果成功,你会看到类似以下的消息:
Hi your_username! You\'ve successfully authenticated, but GitHub does not provide shell access.
-
配置 Git 使用 SSH 协议:
在克隆仓库时使用 SSH URL。git clone git@github.com:username/repository.git
实战示例
假设你希望为你的 GitHub 账户生成和配置 SSH 密钥。
-
生成 SSH 密钥:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
按照提示操作,生成密钥对。
-
添加 SSH 密钥到 SSH 代理:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
-
将公钥添加到 GitHub:
- 登录 GitHub。
- 进入 Settings -> SSH and GPG keys。
- 点击 “New SSH key”,粘贴你的公钥内容(从
~/.ssh/id_rsa.pub
文件中复制),然后保存。
-
测试 SSH 连接:
ssh -T git@github.com
-
配置 Git 使用 SSH 协议:
git clone git@github.com:username/repository.git
设置 GPG 签名以保证提交真实性
GPG(GNU Privacy Guard)签名可以帮助你确保提交的真实性和完整性。以下是生成和配置 GPG 签名的步骤:
-
生成 GPG 密钥:
使用gpg
命令生成 GPG 密钥。gpg --full-generate-key
按照提示选择密钥类型、密钥长度等,并输入个人信息。
-
列出 GPG 密钥:
使用gpg --list-secret-keys --keyid-format LONG
命令查看生成的 GPG 密钥。gpg --list-secret-keys --keyid-format LONG
输出可能如下:
sec rsa4096/XXXXXXXXXXXXXXXX 2023-10-01 [SC]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX uid [ultimate] Your Name <your_email@example.com> ssb rsa4096/YYYYYYYYYYYYYYYY 2023-10-01 [E]
-
配置 Git 使用 GPG 密钥:
设置全局 GPG 密钥 ID。git config --global user.signingkey XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
启用 GPG 签名:
配置 Git 在每次提交时自动签名。git config --global commit.gpgsign true
-
创建带签名的提交:
使用git commit -S
命令创建带签名的提交。git commit -S -m "Your commit message"
-
验证签名:
使用git log --show-signature
命令查看提交日志并验证签名。git log --show-signature
实战示例
假设你希望为你的 Git 提交生成和配置 GPG 签名。
-
生成 GPG 密钥:
gpg --full-generate-key
按照提示操作,生成 GPG 密钥。
-
列出 GPG 密钥:
gpg --list-secret-keys --keyid-format LONG
记下你的 GPG 密钥 ID。
-
配置 Git 使用 GPG 密钥:
git config --global user.signingkey XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
启用 GPG 签名:
git config --global commit.gpgsign true
-
创建带签名的提交:
git commit -S -m "Add new feature with GPG signature"
-
验证签名:
git log --show-signature
相关文章:
协作开发攻略:Git全面使用指南 — 第二部分 高级技巧与最佳实践
协作开发攻略:Git全面使用指南 — 第二部分 高级技巧与最佳实践 Git 是一种分布式版本控制系统,用于跟踪文件和目录的变更。它能帮助开发者有效管理代码版本,支持多人协作开发,方便代码合并与冲突解决,广泛应用于软件开…...
sass 变量
基本使用 如果分配给变量的值后面添加了 !default 标志 ,这意味着该变量如果已经赋值,那么它不会被重新赋值,但是,如果它尚未赋值,那么它会被赋予新的给定值。 如果在此之前变量已经赋值,那就不使用默认值…...
多级缓存架构深度解析:从设计原理到生产实践
多级缓存架构深度解析:从设计原理到生产实践 一、多级缓存架构核心定位与设计原则 1. 架构分层与角色定位 多级缓存通过分层存储、流量削峰、数据分级实现性能与成本的平衡,典型三层架构如下: 层级代表组件存储介质数据特征命中目标成本级…...
(51单片机)LCD展示动画(延时函数)(LLCD1602教程)
前言: 前面我们说过,之前LCD1602模块有点难,但是现在,我们通过几遍博客的学习,今天来讲一下LCD1602的原理 演示视频: LCD1602流动 源代码: main.c #include <STC89C5xRC.H> #include &q…...
12N60-ASEMI无人机专用功率器件12N60
编辑:LL 12N60-ASEMI无人机专用功率器件12N60 型号:12N60 品牌:ASEMI 封装:TO-220F 最大漏源电流:12A 漏源击穿电压:600V 批号:最新 RDS(ON)Max:0.68…...
[Redis] Redis最佳实践
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
arm64适配系列文章-第九章-arm64环境上sentinel的部署
ARM64适配系列文章 第一章 arm64环境上kubesphere和k8s的部署 第二章 arm64环境上nfs-subdir-external-provisioner的部署 第三章 arm64环境上mariadb的部署 第四章 arm64环境上nacos的部署 第五章 arm64环境上redis的部署 第六章 arm64环境上rabbitmq-management的部署 第七章…...
3dmax模型怎么处理3dtiles,制作制作B3DM格式文件
1咱们先打3dmax,或su或者其他软件建模型 2记住面一定一定要少,面一定不能多,也不要是VR材质,可以用插件一键处理 3导出fbx 4使用cesium把fbx转换 5这里可以坐标,因为要对地图位置 6转换出来了,3dtiles格式…...
雪花算法生成int64,在前端js的精度问题
1.问题背景 后端对视频生成唯一性id,在发送评论阶段,由于后端接收的json数据格式,设置videoId为int64。前端于是使用js的Number函数,进行字符串转换为数字,由于不清楚js的精度范围,产生了携带的videoId变化…...
软件测试报告包括哪些内容?可出专业软件测试方案的测评机构推荐
随着信息技术的快速发展,软件质量已经成为决定企业竞争力的重要因素之一。软件测试作为保障软件质量的关键环节,其成果汇总形成的“软件测试报告”在项目生命周期中扮演着重要角色。 软件测试报告就是用来反映测试工作全貌的报告。从测试准备、过程、结…...
dockercompose文件仓库
mysql version: 3 # 使用docker-compose的版本,根据需要可以调整# 创建数据目录 # mkdir -p /home/docker/mysql/mysql_data # mkdir -p /home/docker/mysql/mysql_logs # 给予适当的权限(确保MySQL容器可以读写这些目录) # chmod 777 /ho…...
Docker 的基本概念和优势以及在应用程序开发中的实际应用
Docker 是一种开源的容器化平台,可以让开发者将应用程序及其所有依赖项打包成一个独立的容器,从而实现应用程序的快速部署和运行。下面是 Docker 的基本概念和优势: 基本概念: 容器:一个轻量级、独立的运行环境,包含应用程序及其所有依赖项。镜像:一个只读的模板,用于创…...
JavaWeb:HtmlCss
快速入门 <html><head><title>HTML快速入门</title><head><body><h1>Hello HTML</h1><img src"1.png"></img></body> </html>开发工具vscode 常见便签&样式(新闻࿰…...
linux centOS7.9 No package docker-ce available
docker pull apache/apisix:3.2.2-centos Error response from daemon: missing signature key 处理方式如下: 问题:在纯净机里安装docker时报错No package docker-ce available。 解决办法: 1、更新yum,使用yum -y upgrade&#…...
机器学习(8)——主成分分析
文章目录 1. 主成分分析介绍2. 核心思想3. 数学基础4. 算法步骤4.1. 数据标准化:4.2. 计算协方差矩阵:4.3. 特征分解:4.4. 选择主成分:4.5 降维: 5. 关键参数6. 优缺点7. 改进变种8. 应用场景9. Python示例10. 数学推导…...
使用深度 Q 学习解决Lunar lander问题
使用深度 Q 学习解决Lunar lander问题 0. 前言1. 使用深度 Q 网络解决 Atari 游戏2. 定义环境3. 解决 Lunar lander 问题相关链接 0. 前言 深度 Q 学习模型只需观察状态作为输入就能够解决经典 Atari 游戏,这是一个重大突破,从那时起,深度强…...
centos7使用yum快速安装最新版本Jenkins-2.462.3
Jenkins支持多种安装方式:yum安装、war包安装、Docker安装等。 官方下载地址:https://www.jenkins.io/zh/download 本次实验使用yum方式安装Jenkins LTS长期支持版,版本为 2.462.3。 一、Jenkins基础环境的安装与配置 1.1:基本…...
Bean的生命周期
1.实例化Bean(通过BeanDefinition反射调用无参构造创建对象,如果没有无参构造,需要指定唯一构造方法) 2.给Bean的属性set()赋值 3.检查Bean是否实现了Aware相关接口,实现的话则执行方法 Aware接口:空接口&…...
【缓存与数据库结合方案】伪从技术 vs 直接同步/MQ方案的深度对比
伪从技术 vs 直接同步/MQ方案的深度对比 直接同步修改或通过MQ消息队列也能实现类似同步功能,但伪从技术(通过消费binlog实现数据同步)在某些场景下具有独特优势。下面我将从多个维度进行详细对比分析: 一、核心差异对比表 方案…...
【前端】【业务场景】【面试】在前端开发中,如何实现文件的上传与下载功能,并且处理可能出现的错误情况?
前端文件上传与下载攻略 本文目标:帮你快速掌握文件上传 & 下载的核心实现方式,并在常见出错场景下保持“优雅不崩溃”。 一、文件上传 1. 基础结构 <input type"file" id"fileInput" /> <button id"uploadBtn&…...
【axios取消请求】如何在token过期后取消未响应的请求
功能背景: 我们在实际项目中通常会遇到登录过期后会跳登录页的情况,回跳过程会根据接口请求的状态码判断是否登陆状态过期,并给出用户提示,如果此时存在多个请求接口同时调用,就会同时报出多个登录过期的提示…...
【高频考点精讲】JavaScript中的组合模式:从树形结构到组件嵌套实战
📚 目录 📦 什么是组合模式?🌲 基础版:用组合模式构建一个简单的树形结构💡 举个更真实的场景:菜单组件🧠 为什么组合模式在前端特别重要?🔨 实战案例:组件嵌套组合 + 权限控制🧩 组合模式的延伸用法:搭建 UI DSL 引擎🧪 面试题时间(欢迎评论区作答)组…...
《仙剑奇侠传二》游戏秘籍
无限冥纸:在丰都城,点击特定的小猫,它会给你五张冥纸,再次点击还会再给五张,可循环获取。无限使用虎煞技能:学会 “虎啸风声” 技能后,将虎煞之力值设置为 16,在战斗中持续使用该技能…...
AWS 中国区 CloudFront SSL 证书到期更换实战指南
适用场景: AWS 中国区(宁夏区域 cn-northwest-1 或北京区域 cn-north-1)CloudFront 分配的 SSL 证书到期后无缝替换,域名主体为 domain.cn。 背景与痛点 当 CloudFront 使用的 SSL 证书即将到期时,需手动替换新证书以避免服务中断。由于 AWS 中国区 不支持 ACM 证书,必须…...
【2025A卷】华为OD机试九日集训第3期 - 按算法分类,由易到难,提升编程能力和解题技巧,从而提高机试通过率(Python/JS/C/C++)
目录 一、适合人群二、本期训练时间三、如何参加四、数据结构与算法大纲五、华为OD九日集训第3期第1天、逻辑分析第2天、逻辑分析第3天、双指针第4天、双指针第5天、数据结构map第6天、栈第7天、二叉树第8天、贪心算法第9天、二分查找 六、集训总结国内直接使用最新o3、o4-mini…...
MacOS上如何运行内网穿透详细教程
本文以市面常见、好用的内网穿透为例,一款为开源内网穿透工具Frp;另一款为国产新锐软件ZeroNews。 一、Frp(开源工作、使用自由) 1. 下载 FRP 访问 FRP 的 GitHub 发布页: https://github.com/fatedier/frp/releases 选择适合 …...
第55讲:农业人工智能的跨学科融合与社会影响——构建更加可持续、包容的农业社会
目录 一、农业人工智能的多维融合:科技与社会的桥梁 1. 技术与社会:解决现代农业中的不平等 2. AI与伦理:塑造道德规范与社会责任 3. AI与政策:推动农业政策的科学决策与智能执行 二、AI与农业未来社会的构建:更绿色、更智能、更包容 1. 推动农业可持续发展:绿色农…...
JVM性能优化之老年代参数设置
一、引言 咱们书接上回,上篇文章主要讲解了年轻代参数设置,如果对这一部分还不清楚的建议先去看一下(年轻代参数设置),本文主要为大家介绍老年代参数的设置,掌握好jvm参数的设置是一个高级开发人人员必备的…...
在 Ubuntu 环境为 Elasticsearch 引入 `icu_tokenizer
1. 为什么需要 ICU 分析插件 Elasticsearch 默认的 standard tokenizer 遵循 UAX #29 规则,但在 CJK(中、日、韩)等亚洲语言上仅能按字符切分,无法识别词边界;对包含重音符号、大小写或多脚本混排的文本也缺乏统一归一…...
JMeter 安装及使用 [软件测试工具]
目录 JMeter 1. JMeter 安装 1.1 点击官网下载: JMeter官网下载 1.2 下载后解压即可 1.3 打开 JMeter 1.3.1 方式一: 点击对应程序打开 1.3.2 方式二: 命令行启动 1.4 关闭 JMeter 2. JMeter 基础配置 2.1 修改字体为简体中文 2.2 添加拓展插件 2.2.1 下载其他监听器…...
Unity 资源合理性检测
一:表格过度配置,表格资源是否在工程中存在,并输出不存在的资源 import pandas as pd import glob import osassets [] count 0# 遍历configs文件夹下所有xlsx文件 for file_path in glob.glob(configs/*.xlsx):count 1try:sheets pd.re…...
vue-study(1)
黑马智数项目 黑马智数是一个数字化园区管理项目,该项目后台可以在线管理园区内的楼宇、企业、车辆和一体杆等资源,可视化大屏通过园区3D模型实时展示园区概况。通过该项目能学到如何用qiankun搭建微前端架构、用Echarts进行数据可视化、以及前沿的3D模…...
XS5032:高性能3DNR+HDR ISP-TX 2K芯片
爱芯元智 XS5032:高性能3DNRHDR ISP-TX 2K芯片 视频输入 支持MIPI接口,4lane,Max.1.5Gbps/lane 支持Sensor并口(DVP) 视频分辨率 支持多种同轴高清制式和标清制式,包括: 960H25/30fps&…...
[原创](现代Delphi 12指南):[macOS 64bit App开发]:如何使用NSString类型字符串?
[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...
TDengine 流计算引擎设计
流计算架构 TDengine 流计算的架构如下图所示。当用户输入用于创建流的 SQL 后,首先,该 SQL 将在客户端进行解析,并生成流计算执行所需的逻辑执行计划及其相关属性信息。其次,客户端将这些信息发送至 mnode。mnode 利用来自数据源…...
扩展中国剩余定理
中国剩余定理 中国剩余定理 考虑一组模线性同余方程: { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) . . . x ≡ a k ( m o d m k ) \begin{cases} x\equiv a_1\pmod{m1} \\ x\equiv a_2\pmod{m2}\\ .\\ .\\ .\\ x\equiv a_k\pmod{mk}\\ \end{cases} ⎩ ⎨ ⎧…...
git检查提交分支和package.json的version版本是否一致
这里写自定义目录标题 一、核心实现步骤1.安装必要依赖2.初始化 Husky3.创建校验脚本4.配置 lint-staged5.更新 Husky 钩子 三、工作流程说明四、注意事项 以下是基于 Git Hooks 的完整解决方案,通过 husky 和自定义脚本实现分支名与版本号一致性校…...
Git 详细使用说明文档(适合小白)
Git 详细使用说明文档(适合小白) 1. 什么是 Git? Git 是一个版本控制系统,帮助你管理和跟踪代码的变更。无论是个人项目还是团队协作,Git 都能帮助你记录代码的历史版本,方便回溯和协作。 2. 安装 Git …...
【嵌入式系统设计师(软考中级)】第二章:嵌入式系统硬件基础知识(2)
文章目录 3.嵌入式系统的存储体系3.1 存储系统的层次结构3.2 内存管理单元(MMU)3.3 RAM和ROM的种类3.3.1 RAM类型对比3.3.2 ROM类型对比 3.4 高速缓存(Cache)3.5 其他存储设备3.5.1 新型存储技术3.5.2 外存接口技术 3.嵌入式系统的…...
rk3588 驱动开发(三)第五章 新字符设备驱动实验
register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数,现在新的字符设备驱动已经不再使用这两个函数,而是使用 Linux 内核推荐的新字符设备驱动 API 函数。本节我们就来学习一下如何编写新字符设备驱动,并且在驱动模块加载…...
文件上传--WAF绕过干货
本文主要内容 绕过WAF上传文件 -- 安全狗 -- 宝塔 Burp抓包解析 #上传参数名解析:明确哪些东西能修改? Content-Disposition:—般可更改 name:表单参数值,不能更改 filename:文件名ÿ…...
BERT BERT
BERT ***** 2020年3月11日更新:更小的BERT模型 ***** 这是在《深阅读的学生学得更好:预训练紧凑模型的重要性》(arXiv:1908.08962)中提到的24种较小规模的英文未分词BERT模型的发布。 我们已经证明,标准的BERT架构和…...
Kotlin Multiplatform--02:项目结构进阶
Kotlin Multiplatform--02:项目结构进阶 引言正文 引言 在上一章中,我们对 Kotlin Multiplatform 项目有了基本的了解,已经可以进行开发了。但我们只是使用了系统默认的项目结构。本章介绍了如何进行更复杂的项目结构管理。 正文 在上一章中&…...
【ES实战】Elasticsearch中模糊匹配类的查询
Elasticsearch中模糊匹配类的查询 文章目录 Elasticsearch中模糊匹配类的查询通配符查询前缀匹配查询正则匹配查询标准的正则操作特殊运算符操作 模糊化查询Fuzziness text类型同时配置keyword类型 Elasticsearch中模糊类查询主要有以下 Wildcard Query:通配符查询P…...
纯真社区IP库离线版发布更新
纯真社区IP库离线版发布更新 发布者:技术分享 2005年,随着中国互联网的蓬勃发展,纯真IP库诞生了。作为全球网络空间地理测绘技术的领先者,纯真开源项目为中国互联网行业提供了高质量的网络空间IP库数据。纯真IP库目前已经覆盖超…...
直接偏好优化(Direct Preference Optimization,DPO):论文与源码解析
简介 虽然大规模无监督语言模型(LMs)学习了广泛的世界知识和一些推理技能,但由于它们是基于完全无监督训练,仍很难控制其行为。 微调无监督LM使其对齐偏好,尽管大规模无监督的语言模型(LMs)能…...
uniapp-商城-34-shop 购物车 选好了 进行订单确认
在shop页面选中商品添加到购物车,可选好后,进行确认和支付。具体呈现在shop页面。 1 购物车栏 shop页面代码: 购物车代码: 代码: <template><view><view class"carlayout"><!-- 车里…...
Kafka命令行的使用/Spark-Streaming核心编程(二)
Kafka命令行的使用 创建topic kafka-topics.sh --create --zookeeper node01:2181,node02:2181,node03:2181 --topic test1 --partitions 3 --replication-factor 3 分区数量,副本数量,都是必须的。 数据的形式: 主题名称-分区编号。 在…...
虚拟机详解
虚拟机详解 1. 虚拟机(Virtual Machine)的定义 系统虚拟机:通过软件模拟完整计算机系统(CPU、内存、外设等),如 VMware、VirtualBox。进程级虚拟机:为单个应用提供虚拟执行环境,如 …...
NOIP2013 提高组.转圈游戏
目录 题目算法标签: 数论, 模运算思路代码 题目 504. 转圈游戏 算法标签: 数论, 模运算 思路 看题意不难看出, 计算的是 ( x 1 0 k m ) m o d n (x 10 ^ k \times m) \mod n (x10km)modn, 如果直接计算一定会超时, 因此可以使用快速幂进行优化 代码 #include <iost…...