1.1 任务描述
reflog 是 git 的一个核心的“后悔药”命令。它记录了本地仓库中引用(如 HEAD 和分支)的历史变更。当用户执行了可能丢失提交的操作(如 reset 或错误的 rebase),reflog 可以帮助用户轻松找回这些提交。它是 git 用户广泛依赖的功能。
1.2 实现范围
- 范围内:
- 实现
libra reflog 主命令,展示 HEAD 的变更日志。
- 在所有会修改 HEAD 或分支引用的命令中,集成日志记录逻辑。
- 输出格式与标准
git reflog 默认格式保持相似。
- 可能的范围外:
reflog 的高级子命令和选项,如 delete, expire 等。
- 复杂的输出格式化选项(如
--date)等。
reflog 记录的自动过期清理机制。
2.1 核心命令
- 功能:按时间倒序打印出
HEAD 引用的所有历史变更记录。
- 输出格式:
<new_old_short> HEAD@{<index>}: <action>: <message>。
<new_oid_short>:变更后引用所指向的 Commit OID (SHA-1) 的短哈希。
HEAD@{<index>}:reflog 选择器,{0} 代表最新的一次变更,{1} 是上一次,以此类推。
<action>:描述本次变更是由什么类型的操作触发的。
<message>:对本次变更的详细描述。
a1b2c3d HEAD@{0}: commit: Add user authentication feature
f8e7a6d HEAD@{1}: reset: moving to HEAD~1
c9d0e1f HEAD@{2}: switch: moving from main to feature-branch
...
2.2 日志记录的触发命令和消息格式
commit -> commit message 的第一行。
switch -> moving from <old_branch> to <new_branch>。
reset -> moving to <target_ref>。
merge -> merge <branch_name>:<merge_strategy>。
rebase -> rebase finished: returning to <branch_name>。
pull -> pull: <merge/rebase_details>。
clone -> clone: from <repository_url>。
3. 实现方案
libra 使用 sqlite 来存储一些元数据,可以新建一张表存储所有引用变更日志:
CREATE TABLE reflogs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ref_name TEXT NOT NULL, -- 变更的引用名,如 'HEAD', 'refs/heads/main'
old_oid TEXT NOT NULL, -- 变更前的 OID (SHA-1)
new_oid TEXT NOT NULL, -- 变更后的 OID (SHA-1)
committer_name TEXT NOT NULL, -- 操作者的名字 (从 config 读取)
committer_email TEXT NOT NULL, -- 操作者的邮箱 (从 config 读取)
timestamp INTEGER NOT NULL, -- 操作发生时的 Unix 时间戳
action TEXT NOT NULL, -- 操作类型,如 'commit', 'reset'
message TEXT NOT NULL -- 详细描述信息
);
可以在 ref_name 和 timestamp 上面创建索引。
然后,需要一个统一的,可以复用的函数来处理日志写入,用一个枚举来表示 reflog :
pub enum ActionDetail<'a> {
Commit { message: &'a str },
Reset { target: &'a str },
Switch { from: &'a str, to: &'a str },
Merge { branch: &'a str },
Pull, // 待定
Clone { from: &'a str },
}
pub enum ReflogContext<'a> {
pub old_oid: &'a str,
pub new_oid: &'a str,
pub detail: ActionDetail<'a>,
}
更新变更日志有两种方案:
- 实现一个全新的记录修改日志的函数:
pub fn log_ref_change(
db: &DbConn,
ref_name: &str,
context: &ReflogContext<'_>,
)
- 可以考虑集成到
update_branch 函数里面:
pub async fn update_branch(
branch_name: &str,
commit_hash: &str,
remote: Option<&str>,
context: &ReflogContext<'_>,
)
因为这些操作涉及到多张表的同时变更,所以还需要开启一个事务来保证 ACID。
最后,实现 reflog 的命令行参数。
4. 测试
因为 reflog 涉及到很多其他指令的行为变更,所以还需要为受到影响的指令也进行测试。
1.1 任务描述
reflog是 git 的一个核心的“后悔药”命令。它记录了本地仓库中引用(如 HEAD 和分支)的历史变更。当用户执行了可能丢失提交的操作(如reset或错误的rebase),reflog可以帮助用户轻松找回这些提交。它是 git 用户广泛依赖的功能。1.2 实现范围
libra reflog主命令,展示 HEAD 的变更日志。git reflog默认格式保持相似。reflog的高级子命令和选项,如delete, expire等。--date)等。reflog记录的自动过期清理机制。2.1 核心命令
HEAD引用的所有历史变更记录。<new_old_short> HEAD@{<index>}: <action>: <message>。<new_oid_short>:变更后引用所指向的 Commit OID (SHA-1) 的短哈希。HEAD@{<index>}:reflog选择器,{0}代表最新的一次变更,{1}是上一次,以此类推。<action>:描述本次变更是由什么类型的操作触发的。<message>:对本次变更的详细描述。2.2 日志记录的触发命令和消息格式
commit -> commit message的第一行。switch -> moving from <old_branch> to <new_branch>。reset -> moving to <target_ref>。merge -> merge <branch_name>:<merge_strategy>。rebase -> rebase finished: returning to <branch_name>。pull -> pull: <merge/rebase_details>。clone -> clone: from <repository_url>。3. 实现方案
libra使用 sqlite 来存储一些元数据,可以新建一张表存储所有引用变更日志:可以在
ref_name和timestamp上面创建索引。然后,需要一个统一的,可以复用的函数来处理日志写入,用一个枚举来表示
reflog:更新变更日志有两种方案:
update_branch函数里面:因为这些操作涉及到多张表的同时变更,所以还需要开启一个事务来保证 ACID。
最后,实现
reflog的命令行参数。4. 测试
因为
reflog涉及到很多其他指令的行为变更,所以还需要为受到影响的指令也进行测试。