使用git在整个文件上"接受他们"或"接受我的"的简单工具

nos*_*ian 378 git merge

我不想要一个可视化合并工具,我也不希望vi冲突文件并手动选择HEAD(我的)和导入的更改(他们的)之间.大多数时候我要么想要他们所有的改变,要么全都想要改变.通常这是因为我的改变使它成为了上流,并通过拉动回到我身边,但可能会在不同的地方稍作修改.

是否有一个命令行工具可以摆脱冲突标记并根据我的选择选择所有这些?或者是一组git命令,我可以将自己命名为每个命令.

# accept mine
alias am="some_sequence;of;commands"
alias at="some_other_sequence;of;commands"
Run Code Online (Sandbox Code Playgroud)

这样做很烦人.对于'接受我的',我尝试过:

randy@sabotage ~/linus $ git merge test-branch
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
Automatic merge failed; fix conflicts and then commit the result.

randy@sabotage ~/linus $ git checkout Makefile 
error: path 'Makefile' is unmerged

andy@sabotage ~/linus $ git reset --hard HEAD Makefile 
fatal: Cannot do hard reset with paths.
Run Code Online (Sandbox Code Playgroud)

我怎么能摆脱这些变化标记?

我可以:

git reset HEAD Makefile; rm Makefile; git checkout Makefile
Run Code Online (Sandbox Code Playgroud)

但这似乎相当圆润,必须有更好的方法.在这一点上,我不确定git是否认为合并发生了,所以我认为这甚至不一定有效.

走另一条路,做"接受他们的"同样是凌乱的.我能弄清楚的唯一方法是:

git show test-branch:Makefile > Makefile; git add Makefile;
Run Code Online (Sandbox Code Playgroud)

这也给了我一个混乱的提交消息,它有两次冲突:Makefile.

有人可以指出如何以更简单的方式完成上述两个动作吗?谢谢

Jak*_*ski 573

解决方案非常简单.git checkout <filename>尝试从索引中签出文件,因此在合并时失败.

你需要做的是(即结账提交):

要结帐您自己的版本,您可以使用以下方法之一:

git checkout HEAD -- <filename>
Run Code Online (Sandbox Code Playgroud)

要么

git checkout --ours -- <filename>
Run Code Online (Sandbox Code Playgroud)

要么

git show :2:<filename> > <filename> # (stage 2 is ours)
Run Code Online (Sandbox Code Playgroud)

要签出其他版本,您可以使用以下方法之一:

git checkout test-branch -- <filename>
Run Code Online (Sandbox Code Playgroud)

要么

git checkout --theirs -- <filename>
Run Code Online (Sandbox Code Playgroud)

要么

git show :3:<filename> > <filename> # (stage 3 is theirs)
Run Code Online (Sandbox Code Playgroud)

您还需要运行"添加"以将其标记为已解决:

git add <filename>
Run Code Online (Sandbox Code Playgroud)

  • 我发现有点奇怪的是`--ours`和`--theirs`与我在尝试这个命令时的直觉思想正好相反...... (30认同)
  • @Sammaron @Joshua Muheim;如果您在 rebase 操作的上下文中解决冲突,“他们的”/“我们的”可能会出现交换。因为 rebase 的工作原理是检出目标分支,然后从“你的”分支中挑选提交到目标,传入的更改(“他们的”)来自“你的”分支,当前分支是目标分支(“我们的”) )。 (7认同)
  • 使用`git show`时要小心 - 这会跳过换行标准化. (6认同)
  • @Santhos:Git使用`--`将修订(分支名称等)与路径名(文件名,目录)分开.如果Git无法确定名称是分支的名称还是文件的名称,这一点很重要.这遵循POSIX(或GNU)约定,使用双破折号将参数与参数(文件名)分开. (4认同)
  • 这对于一些文件来说很好,但是当你有很多文件发生冲突时(因为注释中的日期发生了变化!),你是怎么做到的? (2认同)

Siv*_*adi 87

试试这个:

接受他们的变化: git merge --strategy-option theirs

接受你的: git merge --strategy-option ours

  • 请注意,这将保留对所有冲突文件的更改,因此如果发生意外冲突可能会很危险. (5认同)
  • 您可以将其用于其他merge-y命令,例如cherry-pick和rebase。 (2认同)

kyn*_*nan 51

基于Jakub的答案,您可以为方便起见配置以下git别名:

accept-ours = "!f() { git checkout --ours -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
accept-theirs = "!f() { git checkout --theirs -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
Run Code Online (Sandbox Code Playgroud)

他们可选择使用一个或多个文件路径来解析,如果没有给出,则默认解析当前目录下的所有内容.

将它们添加到[alias]~/.gitconfig或运行的部分

git config --global alias.accept-ours '!f() { git checkout --ours -- "${@:-.}"; git add -u "${@:-.}"; }; f'
git config --global alias.accept-theirs '!f() { git checkout --theirs -- "${@:-.}"; git add -u "${@:-.}"; }; f'
Run Code Online (Sandbox Code Playgroud)

  • 你不知道这个别名救了我多少时间.竖起大拇指! (2认同)

小智 17

根据kynan的答案,这里是相同的别名,修改后可以处理文件名中的空格和初始破折号:

accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f"
accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"
Run Code Online (Sandbox Code Playgroud)