首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >git add --带difftool的补丁

git add --带difftool的补丁
EN

Stack Overflow用户
提问于 2012-01-27 03:19:18
回答 5查看 3.2K关注 0票数 28

是否可以将Git配置为在git add --patch中使用已配置的difftool

我想通过我自己的difftool来选择要添加到索引中的更改。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-01-27 03:46:29

不,不幸的是。

我想我可以看到working - Git基于索引中的当前内容生成一个临时文件,将其与当前工作树版本的副本一起传递给difftool (以防止您进行进一步的更改),允许您使用difftool将一些更改移动到索引版本,然后一旦您保存并退出,就会将修改后的索引版本中的任何内容暂存。请注意,这将要求difftool也是一个编辑器,并且并不是所有有效的difftool都是;它们中的一些只是为了查看diffs。还要注意的是,这基本上绕过了所有的git add -p。你不会从它得到任何正常的界面来在大块头之间移动,分割大块头,等等。difftool将完全负责所有这一切。

如果你的difftool功能齐全,可以做这类事情,那么我想你可以写一个脚本来做这件事。一个大纲,没有任何真正的错误保护,处理特殊情况(二进制文件?),并且完全未经测试:

代码语言:javascript
复制
#!/bin/bash
tmpdir=$(mktemp -d)
git diff --name-only |
while read file; do
    cp "$file" $tmpdir
    # this has your changes in it
    work_tree_version="$tmpdir/$file"
    # this has the pristine version
    index_version=$(git checkout-index --temp "$file")
    # and now you bring changes from the work tree version into the index version,
    # within the difftool, and save the index version and quit when done
    my_difftool "$work_tree_version" "$index_version"

    # swap files around to run git add
    mv "$file" "$work_tree_version"
    mv "$index_version" "$file"
    git add "$file"
    mv "$work_tree_version" "$file"
    # you could also do this by calculating the diff and applying it directly to the index
    # git diff --no-index -- "$file" "$original_index_version" | git apply --cached

rm -r $tmpdir

可能有很多方法可以改进它;抱歉,我现在没有时间仔细和彻底地处理它。

票数 12
EN

Stack Overflow用户

发布于 2015-10-17 05:20:12

这是用于此的my script,它打开kdiff3让您执行2个文件的合并。如果您不喜欢kdiff3,可以为MERGETOOLMERGECMD提供您自己的值(但是如果您不喜欢kdiff3,那就太疯狂了)。

为了避免意外,此脚本尝试模仿git add -p作为参数和错误代码。(它同时处理文件和目录的列表。)

此外,它还可以正确地处理各种转角情况,包括:

  • 用户尝试在非git目录中运行脚本(因错误而中止)
  • 用户在完成之前点击Ctrl+C (提前退出)
  • 用户拒绝将合并结果保存在difftool中(然后不使用它,而是转到下一个文件)
  • difftool出现意外错误(提前停止)

示例用法:

代码语言:javascript
复制
$ ## With kdiff3 (default):
$ add-with-mergetool myfile1.txt
$ add-with-mergetool some-directory

$ ## ...or with custom mergetool:
$ export MERGETOOL='opendiff'
$ export MERGECMD='$MERGETOOL $LOCAL $REMOTE -merge $MERGED'
$ add-with-mergetool some-directory/*.py
代码语言:javascript
复制
#!/bin/bash
#
# add-with-mergetool
# Author: Stuart Berg (http://github.com/stuarteberg)
# 
# This little script is like 'git add --patch', except that 
# it launches a merge-tool to perform the merge.

# TODO: For now, this script hard-codes MERGETOOL and MERGECMD for kdiff3.
#       Modify those variables for your own tool if you wish.
#       In the future, it would be nice if we could somehow read  
#       MERGETOOL and MERGECMD from the user's git-config.

# Configure for kdiff3
# (and hide warnings on about modalSession, from kdiff3 on OSX)
MERGETOOL=${MERGETOOL-kdiff3}
MERGECMD=${MERGECMD-'"${MERGETOOL}" "${LOCAL}" "${REMOTE}" -o "${MERGED}"'\
                    2>&1 | grep -iv modalSession}

main() {
    check_for_errors "$@"
    process_all "$@"
}

check_for_errors() {
    which "${MERGETOOL}" > /dev/null
    if [[ $? == 1 ]]; then
        echo "Error: Can't find mergetool: '${MERGETOOL}'" 1>&2
        exit 1
    fi

    if [[ "$1" == "-h" ]]; then
        echo "Usage: $(basename $0) [<pathspec>...]" 1>&2
        exit 0
    fi

    # Exit early if we're not in a git repo
    git status > /dev/null || exit $?
}

process_all() {
    repo_toplevel=$(git rev-parse --show-toplevel)

    # If no args given, add everything (like 'git add -p')
    if [[ $# == 0 ]]; then
        set -- "$repo_toplevel"
    fi

    # For each given file/directory...
    args=( "$@" )
    for arg in "${args[@]}"
    do
        # Find the modified file(s)
        changed_files=( $(git diff --name-only -- "$arg") )
        (
            # Switch to toplevel, to easily handle 'git diff' output
            cd "$repo_toplevel"

            # For each modified file...
            for f in "${changed_files[@]}"
            do
                if [[ $startmsg_shown != "yes" ]]; then
                    echo "Starting $(basename $0).  Use Ctrl+C to stop early."
                    echo "To skip a file, quit ${MERGETOOL} without saving."
                    echo
                    startmsg_shown="yes"
                fi

                # This is where the magic happens.            
                patch_file_and_add "$f"
            done
        ) || exit $? # exit early if loop body failed
    done
}

# This helper function launches the mergetool for a single file,
#  and then adds it to the git index (if the user saved the new file).
patch_file_and_add() {
    f="$1"
    git show :"$f" > "$f.from_index" # Copy from the index
    (
        set -e
        trap "echo && exit 130" INT # Ctrl+C should trigger abnormal exit

        # Execute 2-file merge
        echo "Launching ${MERGETOOL} for '$f'."
        LOCAL="$f.from_index"
        REMOTE="$f"
        MERGED="$f.to_add"
        eval "${MERGECMD}"

        if [[ -e "$f.to_add" ]]; then
            mv "$f" "$f.from_working" # Backup original from working-tree
            mv "$f.to_add" "$f"       # Replace with patched version
            git add "$f"              # Add to the index
            mv "$f.from_working" "$f" # Restore the working-tree version
        fi
    )
    status=$?
    rm "$f.from_index" # Discard the old index version
    if [ $status == 130 ]; then
        echo "User interrupted." 1>&2
        exit $status
    elif [ $status != 0 ]; then
        echo "Error: Interactive add-patch stopped early!" 1>&2
        exit $status
    fi
}

main "$@"
票数 4
EN

Stack Overflow用户

发布于 2019-06-14 21:33:18

如果vimdiff是.gitconfig中的扩散工具:

代码语言:javascript
复制
[diff]
    tool = vimdiff

您也可以站在文件屏幕中执行以下命令:

代码语言:javascript
复制
:!git add %
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9023928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档