如何在Makefile中编译C代码的两个提交版本用于跨版本交互测试
适配C代码多版本编译的集成测试方案
核心原则为全程不要修改当前工作区状态,所有git操作用只读逻辑实现,避免污染未提交的代码变更,也不需要手动切换分支。
方案1:基于git worktree实现(最推荐)
git worktree是git原生的多工作目录管理能力,和主工作区完全隔离,不会产生任何副作用,是当前场景下的最优解,具体实现逻辑如下:
- 先通过只读命令获取两个提交的哈希值:
CUR_COMMIT = $(shell git rev-parse --short HEAD)、PARENT_COMMIT = $(shell git rev-parse --short HEAD^),这两个操作只会读取git信息,不会修改工作区内容 - 给父提交创建独立的临时工作目录:
git worktree add --detach ./build-parent $(PARENT_COMMIT),该目录下的代码完全和父提交一致,和主工作区的当前版本代码互不影响 - 分别进入两个目录编译,产物输出到统一的bin目录,命名区分两个版本避免覆盖
- 测试完成后执行
git worktree remove ./build-parent清理临时目录即可
参考Makefile示例:
CUR_COMMIT := $(shell git rev-parse --short HEAD) PARENT_COMMIT := $(shell git rev-parse --short HEAD^) BIN_DIR := ./bin .PHONY: all test clean all: $(BIN_DIR)/current-$(CUR_COMMIT) $(BIN_DIR)/parent-$(PARENT_COMMIT) # 编译父提交版本产物 $(BIN_DIR)/parent-$(PARENT_COMMIT): @mkdir -p $(BIN_DIR) git worktree add --detach ./build-parent $(PARENT_COMMIT) $(MAKE) -C ./build-parent OUTPUT=../$@ git worktree remove ./build-parent # 编译当前提交版本产物 $(BIN_DIR)/current-$(CUR_COMMIT): @mkdir -p $(BIN_DIR) $(MAKE) OUTPUT=$@ # 执行集成测试 test: all ./your-test-script.sh $(BIN_DIR)/current-$(CUR_COMMIT) $(BIN_DIR)/parent-$(PARENT_COMMIT) clean: rm -rf ./build-parent $(BIN_DIR)
提示:如果父提交的Makefile编译规则和当前版本有差异,可以在执行父版本make命令时传入参数适配,不需要修改历史提交的代码。
方案2:基于git archive导出源码实现
如果你的环境git版本过低不支持worktree,可以用git archive只读导出指定提交的源码,逻辑和方案1类似:
- 执行
git archive $(PARENT_COMMIT) | tar -x -C ./build-parent直接把父提交的源码解压到临时目录 - 后续编译、清理逻辑和方案1完全一致,整个过程也是只读操作,不会修改当前工作区内容
避坑说明
- 禁止在Makefile中直接执行
git checkout切换当前工作区分支,会污染未提交的变更,并行执行任务时还会出现冲突 - 两个版本的编译产物建议带上commit哈希作为后缀,方便出错时快速定位对应版本
- 临时工作目录不要放在git跟踪路径下,避免被误提交
内容的提问来源于stack exchange,提问作者CryptoBipto
相关产品推荐
相关产品推荐

