嵌入式Linux开发Git实战:从认证失败到Gerrit推送全攻略
在嵌入式Linux开发,尤其是龙芯(Loongson)平台的开发过程中,Git是我们日常代码管理和协作的核心工具。但在实际操作中,我们常常会遇到各种Git相关的问题,从认证失败、提交管理,到Gerrit代码审核平台的推送限制。本文将结合笔者的实战经验,系统梳理这些常见问题的解决方案,帮助开发者高效应对。
一、Git推送认证失败(Unauthorized)问题解决
1. 问题现象
在执行git push命令时,终端返回如下错误:
remote: Unauthorized
fatal: Authentication failed for 'http://xxx/xxx.git/'
这表明Git在向远程仓库推送代码时,身份验证失败,导致推送被拒绝。
2. 问题原因
- 本地Git缓存了错误的用户名或密码。
- 输入的用户名/密码/个人访问令牌(PAT)不正确。
- 账号权限不足,无法向目标仓库推送。
3. 解决方案
方案一:清除旧凭证缓存并重新推送
这是最直接有效的方法,步骤如下:
-
清除凭证缓存:
bash# 清除全局凭证助手配置 git config --global --unset credential.helper # 或直接删除本地凭证文件(Linux) rm -rf ~/.git-credentials -
重新推送并正确输入凭证:
bashgit push origin HEAD:refs/for/master%submit当提示输入用户名和密码时,确保输入的信息完全正确。对于GitHub、GitLab等服务,密码处应填写个人访问令牌(PAT)。
方案二:切换到SSH协议(推荐)
为了避免每次推送都输入密码,且提高安全性,建议将远程仓库地址从HTTP/HTTPS切换为SSH协议。
-
查看当前远程地址:
bashgit remote -v -
修改远程地址为SSH格式:
bashgit remote set-url origin git@10.50.122.9:loongson-embedded/pmon-loongson.git -
配置SSH密钥 :
生成并配置SSH公钥到你的Git服务账号,之后即可免密推送。
二、Git提交管理:删除与合并提交
在开发过程中,我们经常需要对提交历史进行整理,例如删除错误的提交或将多个相关提交合并为一个,以保持提交历史的清晰和整洁。
1. 删除上一次提交
场景一:保留提交中的修改(推荐)
当你只想撤销提交记录,但希望保留代码修改,以便后续重新调整和提交时,使用--soft参数:
bash
git reset --soft HEAD~1
HEAD~1:表示回退到上一次提交。- 执行后,上一次提交的修改会被保留在暂存区(Changes to be committed)。
场景二:彻底删除提交及所有修改(谨慎)
当你确认上一次提交的所有修改都是错误的,需要彻底丢弃时,使用--hard参数:
bash
git reset --hard HEAD~1
⚠️ 警告:此操作会永久删除上一次提交的所有修改,且无法通过常规操作恢复,请务必确认后再执行。
已推送至远程的情况
如果上一次提交已经推送到远程仓库,本地删除后,本地与远程的提交历史会不一致。在协作开发中,严禁直接强制推送覆盖远程,这会破坏其他协作者的仓库状态。仅在个人分支或团队明确许可的情况下,才可执行强制推送:
bash
git push -f origin <your-branch-name>
2. 合并前两个提交为一个
为了让提交历史更具逻辑性,我们可以将多个相关的小提交合并为一个有意义的大提交。这里使用git rebase -i(交互式变基)来实现。
-
启动交互式变基:
bashgit rebase -i HEAD~2此命令会打开一个文本编辑器,列出最近的两个提交。
-
编辑提交行为 :
在编辑器中,将需要合并的提交(通常是较新的那个)开头的
pick改为squash(简写s)或fixup(简写f)。-
squash:合并提交,并保留被合并提交的提交信息,之后会让你编辑一个新的合并提交信息。 -
fixup:合并提交,并丢弃被合并提交的提交信息,直接使用主提交的信息,操作更快捷。
示例:s 1234567 第二个提交的备注
pick 7654321 第一个提交的备注
保存并退出编辑器。
-
-
编辑合并后的提交信息 (仅
squash时):如果使用了
squash,会再次打开编辑器,让你编辑合并后的新提交信息。编辑完成后保存退出。 -
验证合并结果:
bashgit log --oneline你会看到原来的两个提交已经被一个新的提交所替代。
三、合并后暂存区的查看与修改
当我们执行git reset --soft HEAD~1或合并提交后,修改会被保留在暂存区。此时,我们需要对暂存区的内容进行查看和调整,以确保最终提交的内容是我们所期望的。
1. 查看暂存区状态
-
查看暂存区文件列表:
bashgit status输出中
Changes to be committed部分列出了所有在暂存区的文件。 -
查看暂存区文件的详细修改:
bash# 查看所有暂存文件的详细变更 git diff --cached # 查看单个文件的详细变更 git diff --cached <file-name>
2. 修改暂存区内容
-
修改文件内容 :
直接用编辑器修改文件,保存后,需要将修改后的文件重新添加到暂存区:
bashgit add <modified-file-name> -
将文件从暂存区移回工作区 :
如果某个文件不想包含在这次提交中,可以将其从暂存区移除,修改会保留在工作区:
bash# 单个文件取消暂存 git restore --staged <file-name> # 所有文件取消暂存 git restore --staged .(旧版Git可使用
git reset HEAD <file-name>) -
将新修改的文件添加到暂存区:
bashgit add <new-file-name>
3. 重新提交
调整完成后,执行提交命令,生成最终的提交:
bash
git commit -m "合并提交:详细描述本次变更"
四、Gerrit推送失败:缺失Change-Id问题
在龙芯等嵌入式开发团队中,Gerrit是常用的代码审核工具。在向Gerrit推送代码时,我们可能会遇到如下错误:
remote: ERROR: commit 0475b7f: missing Change-Id in message footer
remote: error: hook declined to update refs/for/master
To ssh://xxx/xxx.git
! [remote rejected] HEAD -> refs/for/master (missing Change-Id in commit message footer)
error: failed to push some refs to 'ssh://xxx/xxx.git'
1. 问题原因
Gerrit要求每一个提交的信息末尾必须包含一个唯一的Change-Id,用于标识和追踪代码变更。这个Change-Id通常是通过一个名为commit-msg的Git钩子(hook)在提交时自动生成的。本地仓库缺少这个钩子,导致提交时没有生成Change-Id,因此被Gerrit拒绝。
2. 解决方案
-
安装commit-msg钩子 :
按照Gerrit服务器的提示,从服务器下载并安装
commit-msg钩子脚本:bashgitdir=$(git rev-parse --git-dir); scp -P 29418 liupengxiang@10.50.122.9:hooks/commit-msg ${gitdir}/hooks/ -
为当前缺失的提交补充Change-Id :
安装完钩子后,执行以下命令,让钩子为刚才的提交自动生成并插入
Change-Id:bashgit commit --amend --no-edit -
重新推送:
bashgit push origin HEAD:refs/for/master
总结
在嵌入式Linux开发中,Git是我们不可或缺的工具。掌握Git的各种操作,能够极大地提升我们的开发效率和代码管理质量。本文从实际开发场景出发,梳理了Git认证失败、提交管理、暂存区操作以及Gerrit推送等常见问题的解决方案。希望这些经验能够帮助到更多的开发者,让大家在开发道路上少走弯路,更加高效地进行代码协作和管理。
如果你在开发中还遇到了其他Git相关的问题,欢迎在评论区留言交流。