【问题标题】:Git checkout and merge without touching working treeGit结帐和合并而不接触工作树
【发布时间】:2010-11-27 01:01:12
【问题描述】:

假设我有一个功能分支,我在将更改推回之前将上游更改合并到其中:

git branch feature1
... [edit my code]
... [commit]
git fetch origin master
git merge fetch_head [or rebase]
... [resolve conflicts]
... [build and test code]

此时我希望推动我的更改。这样做的正常方法是:

git checkout master [changes a bunch of working tree files]
git merge feature1  [changes the same files right back]

这很好用,但会使(日期检查)编译器认为一大堆文件是脏的,即使内容相同,也需要重新构建。在这种情况下,有没有一种方法可以让工作树保持不变?

类似:

git checkout master --merge-branch feature1

编辑:

我只是在谈论根据定义不会改变文件状态的快进合并。

【问题讨论】:

标签: git


【解决方案1】:

一种简单且安全的方法(无需推送或强制更新)是将 feature1 提取到 master 中:

(feature1)$ git fetch . feature1:master
From .
   4a6000d..8675309  feature1   -> master

诀窍是使用. 来获取 local feature1 参考。这比强制更新 master 分支更安全,因为它确保更新是快进的。 (详见git-fetch documentation中的参数。)

现在 feature1 和 master 是一样的,在它们之间切换不会触及任何文件:

(feature1)$ git checkout master
Switched to branch 'master'
(master)$

【讨论】:

  • 谢谢,这行得通。虽然,我不明白fetch 部分在做什么。
  • @towi 你实际上是在自己做一个git pull 而不更新工作副本(git pull 基本上是git fetchgit merge 的组合)。
  • 这应该是公认的答案。我会在各种情况下不断地回到它:)
【解决方案2】:

[编辑] 这只是部分解决方案/解决方法。请参阅下面@djpohly 的实际答案。

首先,您可以从任何地方推送。不管你检查了什么,或者你想要推送的提交是否在 master 中。

git push REMOTE_REPO feature1:master

git help push

提示:git push remoteRepo localRef:remoteRef

至于将 master 带到您现在所在的位置,而无需摆弄您的工作副本...您可以像这样强制它:

# (while still on feature1 branch)
git checkout -B master origin/master

但这会对master进行硬重置。即它不检查快进。

【讨论】:

  • 没错,解决了一半的问题。即便如此,完成后我也不能真正留在功能分支上。因为我非常想回到主人那里,所以我仍然会遇到这个(相当小)的问题。
  • 好吧,您问题的另一部分(关于希望文件的修改时间以某种方式神奇地更改为正确的事情)并不是真正可以解决的。 git 无法知道何时编译了哪些文件。因此 git 在更改文件时总是会更新时间戳。这会导致一些额外的重新编译,但这比它有时应该重新编译时失败要好得多。
  • 也许您想在您的计算机上再复制一个,这样您就可以同时签出?如果您关心空间,可以让两个本地克隆共享存储库。
  • 我想我希望对于快进合并 git 能够在不触及任何文件的情况下签出和合并(因为它们都不会根据定义而改变)。这没什么大不了的,只是有点不便。
【解决方案3】:

如果不触及工作目录(和索引),合并(或变基)就无法工作,因为可能存在必须使用工作目录(和/或索引)解决的合并冲突。

您始终可以拥有另一个克隆(可能使用替代目录或符号链接对象目录,以节省磁盘空间),或另一个带有contrib/workdir/git-new-workdir 的工作目录。或者使用ccache之类的工具。

编辑: 现在 git worktree 是核心 Git 的一部分,不需要外部工具(至少从 git 版本 2.6.0 开始)。

【讨论】:

  • 不完全。 Git 实际上可以处理多个工作树,因此您可以通过工作“工作树”来执行此操作而无需触摸“工作目录”(您的主要结帐)。不需要额外的克隆或符号链接。见stackoverflow.com/a/58630711/929494
  • @zanerock :在撰写此响应时,git-worktree 位于 contrib/ 中。我已相应地添加到答案中,感谢您的评论。
【解决方案4】:

如果您只关心几个文件并且您使用的是 Unix,您可以使用touch -d <timestamp> 手动更改修复 mtime。确保使用ls --full-time 获取时间戳,因为默认显示缺乏精度。

例如,假设您正在使用 Docker 为基于 Python 的 Web 应用构建映像。如果requirements.txt 文件发生变化,重建需要很长时间,因为它必须下载一堆第三方库并编译它们。合并后只需重置该文件的 mtime:

ls -og --full-time src/requirements.txt
# -rw-r--r-- 1 282 2015-11-04 20:03:28.918979065 +0400 src/requirements.txt

git checkout master
git merge --no-ff feature-foo

touch src/requirements.txt -d "2015-11-04 20:03:28.918979065 +0400"

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2022-10-24
    • 2017-01-02
    • 1970-01-01
    相关资源
    最近更新 更多