嵌入式Linux开发Git实战:从认证到Gerrit推送

嵌入式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. 解决方案

方案一:清除旧凭证缓存并重新推送

这是最直接有效的方法,步骤如下:

  1. 清除凭证缓存

    bash 复制代码
    # 清除全局凭证助手配置
    git config --global --unset credential.helper
    # 或直接删除本地凭证文件(Linux)
    rm -rf ~/.git-credentials
  2. 重新推送并正确输入凭证

    bash 复制代码
    git push origin HEAD:refs/for/master%submit

    当提示输入用户名和密码时,确保输入的信息完全正确。对于GitHub、GitLab等服务,密码处应填写个人访问令牌(PAT)。

方案二:切换到SSH协议(推荐)

为了避免每次推送都输入密码,且提高安全性,建议将远程仓库地址从HTTP/HTTPS切换为SSH协议。

  1. 查看当前远程地址

    bash 复制代码
    git remote -v
  2. 修改远程地址为SSH格式

    bash 复制代码
    git remote set-url origin git@10.50.122.9:loongson-embedded/pmon-loongson.git
  3. 配置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(交互式变基)来实现。

  1. 启动交互式变基

    bash 复制代码
    git rebase -i HEAD~2

    此命令会打开一个文本编辑器,列出最近的两个提交。

  2. 编辑提交行为

    在编辑器中,将需要合并的提交(通常是较新的那个)开头的pick改为squash(简写s)或fixup(简写f)。

    • squash:合并提交,并保留被合并提交的提交信息,之后会让你编辑一个新的合并提交信息。

    • fixup:合并提交,并丢弃被合并提交的提交信息,直接使用主提交的信息,操作更快捷。
      示例:

      s 1234567 第二个提交的备注
      pick 7654321 第一个提交的备注

    保存并退出编辑器。

  3. 编辑合并后的提交信息 (仅squash时):

    如果使用了squash,会再次打开编辑器,让你编辑合并后的新提交信息。编辑完成后保存退出。

  4. 验证合并结果

    bash 复制代码
    git log --oneline

    你会看到原来的两个提交已经被一个新的提交所替代。


三、合并后暂存区的查看与修改

当我们执行git reset --soft HEAD~1或合并提交后,修改会被保留在暂存区。此时,我们需要对暂存区的内容进行查看和调整,以确保最终提交的内容是我们所期望的。

1. 查看暂存区状态

  1. 查看暂存区文件列表

    bash 复制代码
    git status

    输出中Changes to be committed部分列出了所有在暂存区的文件。

  2. 查看暂存区文件的详细修改

    bash 复制代码
    # 查看所有暂存文件的详细变更
    git diff --cached
    
    # 查看单个文件的详细变更
    git diff --cached <file-name>

2. 修改暂存区内容

  1. 修改文件内容

    直接用编辑器修改文件,保存后,需要将修改后的文件重新添加到暂存区:

    bash 复制代码
    git add <modified-file-name>
  2. 将文件从暂存区移回工作区

    如果某个文件不想包含在这次提交中,可以将其从暂存区移除,修改会保留在工作区:

    bash 复制代码
    # 单个文件取消暂存
    git restore --staged <file-name>
    
    # 所有文件取消暂存
    git restore --staged .

    (旧版Git可使用git reset HEAD <file-name>

  3. 将新修改的文件添加到暂存区

    bash 复制代码
    git 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. 解决方案

  1. 安装commit-msg钩子

    按照Gerrit服务器的提示,从服务器下载并安装commit-msg钩子脚本:

    bash 复制代码
    gitdir=$(git rev-parse --git-dir); scp -P 29418 liupengxiang@10.50.122.9:hooks/commit-msg ${gitdir}/hooks/
  2. 为当前缺失的提交补充Change-Id

    安装完钩子后,执行以下命令,让钩子为刚才的提交自动生成并插入Change-Id

    bash 复制代码
    git commit --amend --no-edit
  3. 重新推送

    bash 复制代码
    git push origin HEAD:refs/for/master

总结

在嵌入式Linux开发中,Git是我们不可或缺的工具。掌握Git的各种操作,能够极大地提升我们的开发效率和代码管理质量。本文从实际开发场景出发,梳理了Git认证失败、提交管理、暂存区操作以及Gerrit推送等常见问题的解决方案。希望这些经验能够帮助到更多的开发者,让大家在开发道路上少走弯路,更加高效地进行代码协作和管理。

如果你在开发中还遇到了其他Git相关的问题,欢迎在评论区留言交流。

相关推荐
春日见5 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
小白同学_C5 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
今天只学一颗糖5 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
不做无法实现的梦~7 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
Elastic 中国社区官方博客7 小时前
如何防御你的 RAG 系统免受上下文投毒攻击
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
默|笙9 小时前
【Linux】fd_重定向本质
linux·运维·服务器
陈苏同学9 小时前
[已解决] Solving environment: failed with repodata from current_repodata.json (python其实已经被AutoDL装好了!)
linux·python·conda
“αβ”9 小时前
网络层协议 -- ICMP协议
linux·服务器·网络·网络协议·icmp·traceroute·ping
Elastic 中国社区官方博客9 小时前
Elasticsearch:交易搜索 - AI Agent builder
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索
艺杯羹10 小时前
Git版本控制深度复盘:从入门到精通的完整指南
git·wpf·版本控制·git学习·git复盘