wanshenmean
2026-03-09 b25f84acd529775efe1d43cbcad0142e19ba2182
添加多出库口轮询功能实现计划

- 包含12个详细任务步骤
- 每个步骤包含具体的代码和命令
- 涵盖实现、测试和文档更新
已添加1个文件
675 ■■■■■ 文件已修改
Code/WMS/WIDESEA_WMSServer/docs/plans/2026-03-09-multi-outbound-address-roundrobin-implementation.md 675 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/docs/plans/2026-03-09-multi-outbound-address-roundrobin-implementation.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,675 @@
# å¤šå‡ºåº“口轮询功能实现计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**目标:** æ”¹è¿›è‡ªåŠ¨å‡ºåº“ä»»åŠ¡åŠŸèƒ½ï¼Œæ”¯æŒä¸€ä¸ªå··é“é…ç½®å¤šä¸ªå‡ºåº“å£ï¼Œé€šè¿‡è½®è¯¢ç®—æ³•å®žçŽ°è´Ÿè½½å‡è¡¡
**架构:** ä½¿ç”¨ç‹¬ç«‹çš„ RoundRobinService ç±»ç®¡ç†è½®è¯¢è®¡æ•°å™¨ï¼ŒåŸºäºŽ ConcurrentDictionary å®žçŽ°çº¿ç¨‹å®‰å…¨çš„è½®è¯¢é€‰æ‹©ï¼Œé…ç½®ä»Ž Dictionary<string, string> æ”¹ä¸º Dictionary<string, List<string>>
**技术栈:** .NET 6, ConcurrentDictionary, IOptions æ¨¡å¼, Autofac ä¾èµ–注入
---
## å‰ç½®æ£€æŸ¥
在开始实现前,请确认:
- é¡¹ç›®ä½äºŽ: `d:\Git\ShanMeiXinNengYuan\Code\WMS\WIDESEA_WMSServer`
- å·²é˜…读设计文档: `docs/plans/2026-03-09-multi-outbound-address-roundrobin-design.md`
- å·²å®Œæˆè‡ªåŠ¨å‡ºåº“ä»»åŠ¡çš„åŸºç¡€å®žçŽ° (Tasks 1-7 å·²å®Œæˆ)
---
## Task 1: åˆ›å»º RoundRobinService è½®è¯¢æœåŠ¡ç±»
**Files:**
- Create: `WIDESEA_Core/Core/RoundRobinService.cs`
**Step 1: åˆ›å»º RoundRobinService ç±»**
创建文件 `WIDESEA_Core/Core/RoundRobinService.cs`:
```csharp
using System.Collections.Concurrent;
namespace WIDESEA_Core.Core
{
    /// <summary>
    /// è½®è¯¢æœåŠ¡ - çº¿ç¨‹å®‰å…¨çš„地址轮询选择
    /// </summary>
    public class RoundRobinService
    {
        /// <summary>
        /// è½®è¯¢è®¡æ•°å™¨ - key: å··é“前缀, value: å½“前索引
        /// </summary>
        private readonly ConcurrentDictionary<string, int> _counters = new();
        /// <summary>
        /// èŽ·å–ä¸‹ä¸€ä¸ªåœ°å€ï¼ˆè½®è¯¢ï¼‰
        /// </summary>
        /// <param name="key">巷道前缀标识</param>
        /// <param name="addresses">候选地址列表</param>
        /// <returns>选中的目标地址</returns>
        public string GetNextAddress(string key, List<string> addresses)
        {
            // ç©ºåˆ—表检查
            if (addresses == null || addresses.Count == 0)
                return "10080";
            // å•个地址,直接返回
            if (addresses.Count == 1)
                return addresses[0];
            // å¤šä¸ªåœ°å€ï¼Œä½¿ç”¨è½®è¯¢é€‰æ‹©
            // AddOrUpdate æ˜¯åŽŸå­æ“ä½œï¼Œçº¿ç¨‹å®‰å…¨
            int index = _counters.AddOrUpdate(
                key,
                0,                                      // é¦–次使用,从 0 å¼€å§‹
                (k, oldValue) => (oldValue + 1) % addresses.Count  // è½®è¯¢ï¼šé€’增后取模
            );
            return addresses[index];
        }
    }
}
```
**Step 2: æäº¤ RoundRobinService ç±»**
```bash
git add WIDESEA_Core/Core/RoundRobinService.cs
git commit -m "feat: æ·»åŠ è½®è¯¢æœåŠ¡ç±»æ”¯æŒå¤šå‡ºåº“å£è´Ÿè½½å‡è¡¡"
```
---
## Task 2: ä¿®æ”¹ AutoOutboundTaskOptions é…ç½®æ¨¡åž‹ç±»
**Files:**
- Modify: `WIDESEA_Core/Core/AutoOutboundTaskOptions.cs`
**Step 1: ä¿®æ”¹ TargetAddresses å±žæ€§ç±»åž‹**
读取文件 `WIDESEA_Core/Core/AutoOutboundTaskOptions.cs`,找到 `TargetAddresses` å±žæ€§ï¼Œä¿®æ”¹å¦‚下:
**原代码:**
```csharp
public Dictionary<string, string> TargetAddresses { get; set; }
    = new()
    {
        { "GW", "10081" },
        { "CW", "10080" }
    };
```
**修改为:**
```csharp
public Dictionary<string, List<string>> TargetAddresses { get; set; }
    = new()
    {
        { "GW", new List<string> { "10081" } },
        { "CW", new List<string> { "10080" } }
    };
```
**Step 2: æäº¤é…ç½®æ¨¡åž‹ç±»ä¿®æ”¹**
```bash
git add WIDESEA_Core/Core/AutoOutboundTaskOptions.cs
git commit -m "refactor: TargetAddresses æ”¯æŒå¤šå‡ºåº“口配置"
```
---
## Task 3: æ›´æ–° appsettings.json é…ç½®ç¤ºä¾‹
**Files:**
- Modify: `WIDESEA_WMSServer/appsettings.json`
**Step 1: æ›´æ–° TargetAddresses é…ç½®**
在 `appsettings.json` ä¸­ï¼Œå°† `AutoOutboundTask.TargetAddresses` çš„值从字符串改为数组:
**原配置:**
```json
{
  "AutoOutboundTask": {
    "Enable": true,
    "CheckIntervalSeconds": 300,
    "TargetAddresses": {
      "GW": "10081",
      "CW": "10080"
    }
  }
}
```
**新配置:**
```json
{
  "AutoOutboundTask": {
    "Enable": true,
    "CheckIntervalSeconds": 300,
    "TargetAddresses": {
      "GW": ["10081"],
      "CW": ["10080"]
    }
  }
}
```
**注意:** å¦‚果需要配置多个出库口,可以这样配置:
```json
"TargetAddresses": {
  "GW": ["10081", "10082", "10083"],
  "CW": ["10080"]
}
```
**Step 2: æäº¤é…ç½®æ›´æ–°**
```bash
git add WIDESEA_WMSServer/appsettings.json
git commit -m "config: æ›´æ–° TargetAddresses ä¸ºæ•°ç»„格式"
```
---
## Task 4: åœ¨ TaskService ä¸­æ³¨å…¥ RoundRobinService
**Files:**
- Modify: `WIDESEA_TaskInfoService/TaskService.cs`
**Step 1: æ·»åŠ ç§æœ‰å­—æ®µ**
在 `TaskService` ç±»çš„私有字段区域(大约第 20-30 è¡Œï¼‰ï¼Œæ·»åŠ ï¼š
```csharp
private readonly RoundRobinService _roundRobinService;
```
**Step 2: ä¿®æ”¹æž„造函数**
在构造函数参数中添加 `RoundRobinService roundRobinService`,并赋值:
**找到构造函数:**
```csharp
public TaskService(
    IRepository<Dt_Task> BaseDal,
    IMapper mapper,
    IStockInfoService stockInfoService,
    ILocationInfoService locationInfoService,
    HttpClientHelper httpClientHelper,
    IConfiguration configuration) : base(BaseDal)
{
    _mapper = mapper;
    _stockInfoService = stockInfoService;
    _locationInfoService = locationInfoService;
    _httpClientHelper = httpClientHelper;
    _configuration = configuration;
}
```
**修改为:**
```csharp
public TaskService(
    IRepository<Dt_Task> BaseDal,
    IMapper mapper,
    IStockInfoService stockInfoService,
    ILocationInfoService locationInfoService,
    HttpClientHelper httpClientHelper,
    IConfiguration configuration,
    RoundRobinService roundRobinService) : base(BaseDal)
{
    _mapper = mapper;
    _stockInfoService = stockInfoService;
    _locationInfoService = locationInfoService;
    _httpClientHelper = httpClientHelper;
    _configuration = configuration;
    _roundRobinService = roundRobinService;
}
```
**Step 3: æäº¤æž„造函数修改**
```bash
git add WIDESEA_TaskInfoService/TaskService.cs
git commit -m "refactor: æ³¨å…¥ RoundRobinService"
```
---
## Task 5: ä¿®æ”¹ DetermineTargetAddress æ–¹æ³•
**Files:**
- Modify: `WIDESEA_TaskInfoService/TaskService.cs`
**Step 1: æ‰¾åˆ°å¹¶ä¿®æ”¹ DetermineTargetAddress æ–¹æ³•**
找到 `DetermineTargetAddress` æ–¹æ³•(大约在第 385-397 è¡Œï¼‰ï¼Œå°†å…¶å®Œæ•´æ›¿æ¢ä¸ºï¼š
```csharp
/// <summary>
/// æ ¹æ®å··é“确定目标地址(支持多出库口轮询)
/// </summary>
private string DetermineTargetAddress(string roadway, Dictionary<string, List<string>> addressMap)
{
    if (string.IsNullOrWhiteSpace(roadway))
        return "10080";
    // æŸ¥æ‰¾åŒ¹é…çš„巷道前缀
    string matchedPrefix = null;
    foreach (var kvp in addressMap)
    {
        if (roadway.Contains(kvp.Key))
        {
            matchedPrefix = kvp.Key;
            break;
        }
    }
    if (matchedPrefix == null)
        return "10080";
    var addresses = addressMap[matchedPrefix];
    if (addresses == null || addresses.Count == 0)
        return "10080";
    // å•个地址,直接返回
    if (addresses.Count == 1)
        return addresses[0];
    // å¤šä¸ªåœ°å€ï¼Œä½¿ç”¨è½®è¯¢æœåŠ¡
    return _roundRobinService.GetNextAddress(matchedPrefix, addresses);
}
```
**Step 2: æäº¤æ–¹æ³•修改**
```bash
git add WIDESEA_TaskInfoService/TaskService.cs
git commit -m "feat: æ”¯æŒå¤šå‡ºåº“口轮询选择"
```
---
## Task 6: åœ¨ Program.cs ä¸­æ³¨å†Œ RoundRobinService
**Files:**
- Modify: `WIDESEA_WMSServer/Program.cs`
**Step 1: æ·»åŠ  RoundRobinService æ³¨å†Œ**
在 `Program.cs` ä¸­ï¼Œæ‰¾åˆ°é…ç½®æ³¨å†ŒåŒºåŸŸï¼ˆå¤§çº¦ç¬¬ 43-45 è¡Œï¼‰ï¼Œåœ¨ `AddAllOptionRegister()` ä¹‹åŽæ·»åŠ ï¼š
```csharp
builder.Services.AddSingleton<RoundRobinService>();
```
**完整上下文:**
```csharp
builder.Services.AddAllOptionRegister();
builder.Services.AddSingleton<RoundRobinService>();  // æ–°å¢ž
builder.Services.AddMemoryCacheSetup();
```
**Step 2: æäº¤æœåŠ¡æ³¨å†Œ**
```bash
git add WIDESEA_WMSServer/Program.cs
git commit -m "config: æ³¨å†Œ RoundRobinService ä¸ºå•例服务"
```
---
## Task 7: ç¼–译验证
**Step 1: ç¼–译项目**
```bash
cd WIDESEA_WMSServer
dotnet build --configuration Release
```
**预期输出:** ç¼–译成功,0 ä¸ªé”™è¯¯
**Step 2: æ£€æŸ¥ç¼–译结果**
确认输出包含:
```
Build succeeded.
    0 Warning(s)
    0 Error(s)
```
**Step 3: å¦‚有错误,根据错误信息修复**
常见问题:
- ç¼ºå°‘ `using System.Collections.Generic;` â†’ æ·»åŠ å‘½åç©ºé—´
- `RoundRobinService` æ‰¾ä¸åˆ° â†’ æ£€æŸ¥å‘½åç©ºé—´å’Œæ³¨å†Œ
---
## Task 8: æ‰‹åŠ¨æµ‹è¯• - å•出库口
**Step 1: ç¡®è®¤é…ç½®ä¸ºå•出库口格式**
检查 `appsettings.json` ä¸­çš„配置:
```json
{
  "AutoOutboundTask": {
    "TargetAddresses": {
      "GW": ["10081"],
      "CW": ["10080"]
    }
  }
}
```
**Step 2: å‡†å¤‡æµ‹è¯•数据**
在数据库中执行:
```sql
-- è®¾ç½®æµ‹è¯•库存的出库日期为过去时间
UPDATE Dt_StockInfo
SET OutboundDate = DATEADD(MINUTE, -5, GETDATE())
WHERE PalletCode = 'TEST001' AND StockStatus = 1;
```
**Step 3: å¯åŠ¨åº”ç”¨**
```bash
cd WIDESEA_WMSServer
dotnet run
```
**Step 4: è§‚察日志输出**
预期看到:
```
info: è‡ªåŠ¨å‡ºåº“ä»»åŠ¡åŽå°æœåŠ¡å·²å¯åŠ¨
info: åˆ°æœŸåº“存检查完成: æˆåŠŸåˆ›å»º 1 ä¸ªå‡ºåº“任务
```
**Step 5: éªŒè¯æ•°æ®åº“**
```sql
SELECT TaskNum, PalletCode, TargetAddress FROM Dt_Task
WHERE PalletCode = 'TEST001' AND Creater = 'system_auto'
```
预期 `TargetAddress` ä¸ºé…ç½®çš„地址(如 "10081")
**Step 6: æ¸…理测试数据**
```sql
DELETE FROM Dt_Task WHERE PalletCode = 'TEST001'
UPDATE Dt_StockInfo SET OutboundDate = NULL WHERE PalletCode = 'TEST001'
```
---
## Task 9: æ‰‹åŠ¨æµ‹è¯• - å¤šå‡ºåº“口轮询
**Step 1: ä¿®æ”¹é…ç½®ä¸ºå¤šå‡ºåº“口**
更新 `appsettings.json`:
```json
{
  "AutoOutboundTask": {
    "TargetAddresses": {
      "GW": ["10081", "10082", "10083"],
      "CW": ["10080"]
    }
  }
}
```
**Step 2: å‡†å¤‡å¤šä¸ªæµ‹è¯•库存**
```sql
UPDATE Dt_StockInfo
SET OutboundDate = DATEADD(MINUTE, -5, GETDATE())
WHERE PalletCode IN ('TEST001', 'TEST002', 'TEST003', 'TEST004', 'TEST005')
  AND StockStatus = 1
  AND LocationCode LIKE '%GW%';  -- ç¡®ä¿ä½¿ç”¨ GW å··é“
```
**Step 3: å¯åŠ¨åº”ç”¨å¹¶è§‚å¯Ÿæ—¥å¿—**
```bash
dotnet run
```
**Step 4: éªŒè¯è½®è¯¢åˆ†é…**
```sql
SELECT TaskNum, PalletCode, TargetAddress
FROM Dt_Task
WHERE PalletCode IN ('TEST001', 'TEST002', 'TEST003', 'TEST004', 'TEST005')
  AND Creater = 'system_auto'
ORDER BY CreateDate
```
预期 `TargetAddress` æŒ‰è½®è¯¢é¡ºåºåˆ†é…ï¼š10081, 10082, 10083, 10081, 10082...
**Step 5: æ¸…理测试数据**
```sql
DELETE FROM Dt_Task WHERE PalletCode IN ('TEST001', 'TEST002', 'TEST003', 'TEST004', 'TEST005')
UPDATE Dt_StockInfo
SET OutboundDate = NULL
WHERE PalletCode IN ('TEST001', 'TEST002', 'TEST003', 'TEST004', 'TEST005')
```
---
## Task 10: å¹¶å‘安全测试
**Step 1: åˆ›å»ºæµ‹è¯•脚本**
创建一个简单的 PowerShell è„šæœ¬ `test-concurrent.ps1`:
```powershell
# æ¨¡æ‹Ÿå¹¶å‘创建任务
$tasks = 1..10 | ForEach-Object {
    Start-ThreadJob -ScriptBlock {
        # è°ƒç”¨åˆ›å»ºä»»åŠ¡çš„ API æˆ–直接操作数据库
        # è¿™é‡Œç®€åŒ–为模拟
        Start-Sleep -Milliseconds (Get-Random -Minimum 10 -Maximum 100)
    }
}
Wait-Job -Job $tasks
Receive-Job -Job $tasks
```
**Step 2: è§‚察轮询计数器**
在后台服务中添加临时日志(测试后删除):
在 `RoundRobinService.GetNextAddress` ä¸­æ·»åŠ ï¼š
```csharp
Console.WriteLine($"[RoundRobin] Key={key}, Index={index}, Address={addresses[index]}");
```
**Step 3: éªŒè¯çº¿ç¨‹å®‰å…¨**
- å¤šä¸ªä»»åŠ¡åŒæ—¶åˆ›å»º
- è®¡æ•°å™¨é€’增不出现重复或跳跃
- åœ°å€åˆ†é…å‡åŒ€
**Step 4: ç§»é™¤è°ƒè¯•日志**
测试完成后,移除添加的日志语句。
**Step 5: æäº¤å¹¶å‘测试代码(如果创建了独立测试项目)**
```bash
git add -A
git commit -m "test: æ·»åŠ å¹¶å‘å®‰å…¨æµ‹è¯•"
```
---
## Task 11: æ›´æ–°è®¾è®¡æ–‡æ¡£
**Files:**
- Modify: `docs/plans/2026-03-09-multi-outbound-address-roundrobin-design.md`
**Step 1: æ›´æ–°å®žæ–½çŠ¶æ€**
在设计文档末尾的"实施清单"部分,更新状态:
```markdown
## å®žæ–½æ¸…单
- [x] ä¿®æ”¹ `AutoOutboundTaskOptions.TargetAddresses` ç±»åž‹
- [x] åˆ›å»º `RoundRobinService` ç±»
- [x] ä¿®æ”¹ `TaskService.DetermineTargetAddress` æ–¹æ³•
- [x] åœ¨ `Program.cs` æ³¨å†Œ `RoundRobinService`
- [x] æ›´æ–° `appsettings.json` é…ç½®ç¤ºä¾‹
- [x] ç¼–译验证
- [x] æ‰‹åŠ¨æµ‹è¯•
- [x] å¹¶å‘安全测试
- [x] æ›´æ–°è®¾è®¡æ–‡æ¡£
**实施日期**: 2026-03-09
**实施人**: Claude Code
**状态**: å·²å®Œæˆ
```
**Step 2: æäº¤æ–‡æ¡£æ›´æ–°**
```bash
git add docs/plans/2026-03-09-multi-outbound-address-roundrobin-design.md
git commit -m "docs: æ›´æ–°è®¾è®¡æ–‡æ¡£å®žæ–½çŠ¶æ€"
```
---
## Task 12: æœ€ç»ˆéªŒè¯
**Step 1: è¿è¡Œå®Œæ•´ç¼–译**
```bash
cd ..
dotnet build WIDESEA_WMSServer/WIDESEA_WMSServer.csproj --configuration Release
```
**Step 2: ç¡®è®¤æ‰€æœ‰æ–‡ä»¶å·²æäº¤**
```bash
git status
```
预期输出:`nothing to commit, working tree clean`
**Step 3: æŸ¥çœ‹æäº¤åŽ†å²**
```bash
git log --oneline -10
```
**Step 4: éªŒè¯åŠŸèƒ½å®Œæ•´æ€§**
检查清单:
- [ ] `RoundRobinService` ç±»å·²åˆ›å»ºå¹¶æ³¨å†Œ
- [ ] `AutoOutboundTaskOptions` ç±»åž‹å·²ä¿®æ”¹
- [ ] `TaskService.DetermineTargetAddress` å·²æ›´æ–°
- [ ] `appsettings.json` é…ç½®æ ¼å¼å·²æ›´æ–°
- [ ] ç¼–译成功,0 é”™è¯¯
- [ ] å•出库口测试通过
- [ ] å¤šå‡ºåº“口轮询测试通过
- [ ] å¹¶å‘安全验证通过
---
## å®Œæˆæ£€æŸ¥æ¸…单
- [ ] æ‰€æœ‰ä»£ç æ–‡ä»¶å·²åˆ›å»º/修改
- [ ] æ‰€æœ‰ä»£ç å·²ç¼–译通过
- [ ] é…ç½®æ–‡ä»¶å·²æ›´æ–°
- [ ] å•出库口测试已完成
- [ ] å¤šå‡ºåº“口轮询测试已完成
- [ ] å¹¶å‘安全测试已完成
- [ ] æ–‡æ¡£å·²æ›´æ–°
- [ ] æ‰€æœ‰æ›´æ”¹å·²æäº¤åˆ° git
---
## æ•…障排查
### ç¼–译错误
**问题**: æ‰¾ä¸åˆ° `RoundRobinService` ç±»åž‹
**解决**:
1. ç¡®è®¤ `WIDESEA_Core/Core/RoundRobinService.cs` æ–‡ä»¶å­˜åœ¨
2. æ£€æŸ¥å‘½åç©ºé—´æ˜¯å¦æ­£ç¡®ï¼š`WIDESEA_Core.Core`
3. ç¡®è®¤ `TaskService.cs` ä¸­æœ‰æ­£ç¡®çš„ using å¼•用
**问题**: `Dictionary<string, List<string>>` ç»‘定失败
**解决**:
1. æ£€æŸ¥ `appsettings.json` æ ¼å¼æ˜¯å¦æ­£ç¡®
2. ç¡®è®¤ JSON æ•°ç»„格式:`"GW": ["10081", "10082"]`
3. æ£€æŸ¥æ˜¯å¦æœ‰é€—号分隔符错误
### è¿è¡Œæ—¶é”™è¯¯
**问题**: è½®è¯¢ä¸ç”Ÿæ•ˆï¼Œæ€»æ˜¯è¿”回第一个地址
**解决**:
1. æ£€æŸ¥é…ç½®ä¸­åœ°å€æ•°ç»„是否真的有多个元素
2. ç¡®è®¤ `RoundRobinService` å·²æ³¨å†Œä¸ºå•例
3. éªŒè¯ `GetNextAddress` æ–¹æ³•被正确调用
**问题**: åº”用启动失败,提示依赖注入错误
**解决**:
1. ç¡®è®¤ `RoundRobinService` åœ¨ `Program.cs` ä¸­å·²æ³¨å†Œ
2. æ£€æŸ¥ `TaskService` æž„造函数是否正确接收该参数
3. éªŒè¯ Autofac é…ç½®
### æµ‹è¯•问题
**问题**: æµ‹è¯•数据没有创建任务
**解决**:
1. ç¡®è®¤åº“存的 `OutboundDate` å·²è¿‡æœŸ
2. æ£€æŸ¥åº“存状态为"入库完成"
3. éªŒè¯åŽå°æœåŠ¡å·²å¯åŠ¨ï¼ˆæŸ¥çœ‹æ—¥å¿—ï¼‰
**问题**: è½®è¯¢é¡ºåºä¸å¯¹
**解决**:
1. æ£€æŸ¥ `GetNextAddress` ä¸­çš„æ¨¡è¿ç®—逻辑
2. éªŒè¯ `AddOrUpdate` çš„æ›´æ–°å‡½æ•°æ˜¯å¦æ­£ç¡®
3. ç¡®è®¤æ²¡æœ‰å¤šä¸ª `RoundRobinService` å®žä¾‹
---
## æ€§èƒ½æŒ‡æ ‡
预期性能:
- **单次地址选择**: < 1 å¾®ç§’(内存操作)
- **并发 100 çº¿ç¨‹**: æ— é”ç«žäº‰ï¼Œçº¿æ€§æ‰©å±•
- **内存开销**: æ¯ä¸ªå··é“前缀约 50 å­—节
---
## å›žæ»šæ–¹æ¡ˆ
如需回滚到原版本:
1. **恢复配置**:
```json
"TargetAddresses": {
  "GW": "10081",
  "CW": "10080"
}
```
2. **恢复代码**:
```bash
git revert <commit-hash-range>
```
3. **或使用 git reset**(谨慎使用):
```bash
git reset --hard <before-implementation-commit>
```