合并而不更改工作目录 [英] Merging without changing the working directory

查看:64
本文介绍了合并而不更改工作目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下场景:

  * ab82147(HEAD,topic)changes 
* 8993636 changes
* 82f4426更改
* 18be5a3(主)首先

我想合并(非快进)主题转换为 master 。这要求我:


  • git checkout master

  • git merge --no-ff topic



然后将主题合并到它中会导致git更改我的工作目录(尽管最终结果与检查主文件之前的结果相同),并且我遇到的问题是由于我们项目的大小所致,大约需要30分钟的时间来构建它(使用IncrediBuild),尽管没有真正改变,它简直无法忍受。



所以我想得到的是以下内容:

  * 9075cf4(HEAD,master)合并分支'主题'
| \
| * ab82147(主题)更改
| * 8993636更改
| * 82f4426变更
| /
* 18be5a3先

目录(或至少欺骗git)。

解决方案

有趣!我不认为有内置的方法可以做到这一点,但是您应该可以使用管道软件来实现它:

 #!/ bin / bash 

branch = master
#或带参数:
#if [$ @ eq 1];
#branch =$ 1;
#fi

#确保分支存在
if! git rev-parse --verify --quiet --heads$ branch>的/ dev / null的;那么
echoerror:branch $ branch does not exist
exit 1
fi

#确保这可能是一个快进
if [$(git merge-base HEAD $ branch)==$(git rev-parse $ branch)];然后
#找到与HEAD相关的分支名称
currentbranch = $(git symbolic-ref HEAD | sed's @。* / @@')
#提交
newcommit = $(echoMerge branch'$ currentbranch'| git commit-tree $(git log -n 1 --pretty =%T HEAD)-p $ branch -p HEAD)
#将分支移动到指向新的提交
git update-ref -mmerge $ currentbranch:通过模拟的no-ff进行合并refs / heads / $ branch$ newcommit
else
echoerror :将$ currentbranch合并到$ branch不会是快进的
exit 1
fi

有趣的是 newcommit = line;它使用提交树来直接创建合并提交。第一个参数是要使用的树;那是树头,你想保留其内容的分支。提交消息由stdin提供,其余参数命名新提交应该具有的父项。提交的SHA1被打印到stdout,所以假设提交成功,你捕获它,然后合并该提交(这将是一个快进)。如果你很迷恋,你可以确保提交树成功 - 但这应该是非常有保证的。



局限性:




  • 这只适用于本来可以快速转换的合并。在这种情况下,显然你必须检出并合并(可能在克隆中保存你的构建系统)。
  • reflog消息是不同的。我故意这样做,因为当你使用 - no-ff 时,git实际上会强制自己使用默认(递归)策略,但是在reflog中写入是一个谎言。

  • 如果你处于独立HEAD模式,事情会变得很糟糕。那就必须特别对待。



是的,我在玩具回购库上测试了它,它似乎正常工作! (尽管我没有努力去打破它。)


I have the following scenario:

* ab82147 (HEAD, topic) changes
* 8993636 changes
* 82f4426 changes
* 18be5a3 (master) first

I'd like to merge (non fast-forward) topic into master. This requires me to:

  • git checkout master
  • git merge --no-ff topic

But checking out master, and then merging topic into it causes git to change my working directory (although the final result is identical to the one before checking out master), and the problem I have with that is due to the size of our project, it takes about 30 minutes to build it (with IncrediBuild) although nothing really changed and it's simply unbearable.

So what I would like to get is the following:

*   9075cf4 (HEAD, master) Merge branch 'topic'
|\  
| * ab82147 (topic) changes
| * 8993636 changes
| * 82f4426 changes
|/  
* 18be5a3 first

Without really touching the working directory (or at least cheating git somehow).

解决方案

Interesting! I don't think there's a built-in way to do this, but you should be able to fudge it using the plumbing:

#!/bin/bash

branch=master
# or take an argument:
# if [ $@ eq 1 ];
#      branch="$1";
# fi

# make sure the branch exists
if ! git rev-parse --verify --quiet --heads "$branch" > /dev/null; then
     echo "error: branch $branch does not exist"
     exit 1
fi

# make sure this could be a fast-forward   
if [ "$(git merge-base HEAD $branch)" == "$(git rev-parse $branch)" ]; then
    # find the branch name associated with HEAD
    currentbranch=$(git symbolic-ref HEAD | sed 's@.*/@@')
    # make the commit
    newcommit=$(echo "Merge branch '$currentbranch'" | git commit-tree $(git log -n 1 --pretty=%T HEAD) -p $branch -p HEAD)
    # move the branch to point to the new commit
    git update-ref -m "merge $currentbranch: Merge made by simulated no-ff" "refs/heads/$branch" $newcommit
else
    echo "error: merging $currentbranch into $branch would not be a fast-forward"
    exit 1
fi

The interesting bit is that newcommit= line; it uses commit-tree to directly create the merge commit. The first argument is the tree to use; that's the tree HEAD, the branch whose contents you want to keep. The commit message is supplied on stdin, and the rest of the arguments name the parents the new commit should have. The commit's SHA1 is printed to stdout, so assuming the commit succeeded, you capture that, then merge that commit (that'll be a fast-forward). If you're obsessive, you could make sure that commit-tree succeeded - but that should be pretty much guaranteed.

Limitations:

  • This only works on merges that could have been a fast-forward. Obviously you'll actually have to check out and merge (possibly in a clone, to save your build system) in that case.
  • The reflog message is different. I did this deliberately, because when you use --no-ff, git will actually force itself to use the default (recursive) strategy, but to write that in the reflog would be a lie.
  • If you're in detached HEAD mode, things will go badly. That would have to be treated specially.

And yes, I tested this on a toy repo, and it appears to work properly! (Though I didn't try hard to break it.)

这篇关于合并而不更改工作目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆