git-sync-web 自动提交 2026-09-08 18:21:40
This commit is contained in:
@@ -531,6 +531,7 @@ func (e *Engine) syncOnce(s *repoState, trigger string) {
|
|||||||
// 分支对齐:本地当前分支与配置不一致时,自动切换/创建(对齐原 bash 脚本行为)
|
// 分支对齐:本地当前分支与配置不一致时,自动切换/创建(对齐原 bash 脚本行为)
|
||||||
// 否则 push 会因 src refspec 不存在而失败
|
// 否则 push 会因 src refspec 不存在而失败
|
||||||
if cur, cerr := currentBranch(cfg.RepoPath); cerr == nil && cur != cfg.Branch {
|
if cur, cerr := currentBranch(cfg.RepoPath); cerr == nil && cur != cfg.Branch {
|
||||||
|
tip, remoteHasBranch := remoteTip(cfg.RepoPath, remote, cfg.Branch)
|
||||||
switch {
|
switch {
|
||||||
case branchExists(cfg.RepoPath, cfg.Branch):
|
case branchExists(cfg.RepoPath, cfg.Branch):
|
||||||
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", cfg.Branch); err != nil {
|
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", cfg.Branch); err != nil {
|
||||||
@@ -538,12 +539,12 @@ func (e *Engine) syncOnce(s *repoState, trigger string) {
|
|||||||
} else {
|
} else {
|
||||||
e.logf(s, "info", "本地分支与配置不一致(%s → %s),已自动切换", cur, cfg.Branch)
|
e.logf(s, "info", "本地分支与配置不一致(%s → %s),已自动切换", cur, cfg.Branch)
|
||||||
}
|
}
|
||||||
case remoteRefExists(cfg.RepoPath, remote, cfg.Branch):
|
case remoteHasBranch:
|
||||||
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", "-B", cfg.Branch, remote+"/"+cfg.Branch); err != nil {
|
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", "-B", cfg.Branch, tip); err != nil {
|
||||||
e.logf(s, "warn", "基于 %s/%s 创建分支失败: %v(继续在 %s 上同步)", remote, cfg.Branch, err, cur)
|
e.logf(s, "warn", "基于远程 %s 创建分支失败: %v(继续在 %s 上同步)", cfg.Branch, err, cur)
|
||||||
} else {
|
} else {
|
||||||
_, _ = gitRun(cfg.RepoPath, 15*time.Second, "branch", "--set-upstream-to", remote+"/"+cfg.Branch, cfg.Branch)
|
_, _ = gitRun(cfg.RepoPath, 15*time.Second, "branch", "--set-upstream-to", remote+"/"+cfg.Branch, cfg.Branch)
|
||||||
e.logf(s, "info", "本地无分支 %s,已基于 %s/%s 创建并跟踪", cfg.Branch, remote, cfg.Branch)
|
e.logf(s, "info", "本地无分支 %s,已基于远程 %s(%s)创建并跟踪", cfg.Branch, cfg.Branch, tip[:8])
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", "-B", cfg.Branch); err != nil {
|
if _, err := gitRun(cfg.RepoPath, 30*time.Second, "checkout", "-B", cfg.Branch); err != nil {
|
||||||
@@ -576,8 +577,9 @@ func (e *Engine) syncOnce(s *repoState, trigger string) {
|
|||||||
|
|
||||||
var ahead, behind int
|
var ahead, behind int
|
||||||
var err error
|
var err error
|
||||||
if remoteRefExists(cfg.RepoPath, remote, cfg.Branch) {
|
tip, remoteHasBranch := remoteTip(cfg.RepoPath, remote, cfg.Branch)
|
||||||
ahead, behind, err = aheadBehind(cfg.RepoPath, remote, cfg.Branch)
|
if remoteHasBranch {
|
||||||
|
ahead, behind, err = aheadBehindSha(cfg.RepoPath, tip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.setFail(s, "获取领先/落后信息失败: "+err.Error())
|
e.setFail(s, "获取领先/落后信息失败: "+err.Error())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -87,6 +87,42 @@ func branchExists(path, branch string) bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remoteTip 返回远程分支当前指向的 SHA。
|
||||||
|
// 优先读本地远程跟踪引用(refs/remotes/<remote>/<branch>,快);
|
||||||
|
// 若本地跟踪引用不可用(个别环境下 ref 存储读写异常),回退用 ls-remote 直查远程。
|
||||||
|
func remoteTip(path, remote, branch string) (sha string, exists bool) {
|
||||||
|
if remoteRefExists(path, remote, branch) {
|
||||||
|
out, err := gitRun(path, 15*time.Second, "rev-parse", remote+"/"+branch)
|
||||||
|
if err == nil {
|
||||||
|
return strings.TrimSpace(out), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out, err := gitRun(path, 30*time.Second, "ls-remote", remote, "refs/heads/"+branch)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
fields := strings.Fields(strings.TrimSpace(out))
|
||||||
|
if len(fields) < 2 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return fields[0], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// aheadBehindSha 基于远程分支的具体 SHA 计算 (领先, 落后),不依赖本地跟踪引用
|
||||||
|
func aheadBehindSha(path, tip string) (int, int, error) {
|
||||||
|
out, err := gitRun(path, 30*time.Second, "rev-list", "--left-right", "--count", "HEAD..."+tip)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
parts := strings.Fields(out)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return 0, 0, fmt.Errorf("无法解析 rev-list 输出: %q", out)
|
||||||
|
}
|
||||||
|
a, _ := strconv.Atoi(parts[0])
|
||||||
|
b, _ := strconv.Atoi(parts[1])
|
||||||
|
return a, b, nil
|
||||||
|
}
|
||||||
|
|
||||||
func dirtyCount(path string) int {
|
func dirtyCount(path string) int {
|
||||||
out, err := gitRun(path, 30*time.Second, "status", "--porcelain")
|
out, err := gitRun(path, 30*time.Second, "status", "--porcelain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -175,3 +175,10 @@ hint: See the 'Note about fast-forwards' in 'git push --help' for details.
|
|||||||
[2026-09-08 18:13:59] 推送失败,本轮同步已终止(跳过拉取以避免分叉加剧)
|
[2026-09-08 18:13:59] 推送失败,本轮同步已终止(跳过拉取以避免分叉加剧)
|
||||||
[2026-09-08 18:14:59] === 开始同步(定时检查,模式 push)===
|
[2026-09-08 18:14:59] === 开始同步(定时检查,模式 push)===
|
||||||
[2026-09-08 18:15:09] 检测到 2 个未提交改动,执行自动提交
|
[2026-09-08 18:15:09] 检测到 2 个未提交改动,执行自动提交
|
||||||
|
[2026-09-08 18:15:13] 自动提交完成,将随本轮同步推送
|
||||||
|
[2026-09-08 18:15:15] 远程分支 origin/main 不存在(远程仓库可能为空或分支名不一致),将推送本地 23 个提交以建立远程分支
|
||||||
|
[2026-09-08 18:20:25] 推送至 origin 失败: 命令超时: git push origin main
|
||||||
|
[2026-09-08 18:20:25] 推送失败,本轮同步已终止(跳过拉取以避免分叉加剧)
|
||||||
|
[2026-09-08 18:21:31] 监控已启动
|
||||||
|
[2026-09-08 18:21:31] === 开始同步(启动检查,模式 push)===
|
||||||
|
[2026-09-08 18:21:40] 检测到 4 个未提交改动,执行自动提交
|
||||||
|
|||||||
@@ -20,3 +20,4 @@ timestamp,action,result,commits
|
|||||||
2026-09-08 18:01:06,push,failed,20
|
2026-09-08 18:01:06,push,failed,20
|
||||||
2026-09-08 18:07:32,push,failed,21
|
2026-09-08 18:07:32,push,failed,21
|
||||||
2026-09-08 18:13:59,push,failed,22
|
2026-09-08 18:13:59,push,failed,22
|
||||||
|
2026-09-08 18:20:25,push,failed,23
|
||||||
|
|||||||
|
Reference in New Issue
Block a user