Git one-liner for applying a patch interactively

3.8k Views Asked by At

I have this patch file, it contains a bunch of modifications that I'd like to apply to a git branch. But I don't want to make one unique commit with all those modifications, instead I'd like to split it into 2 or 3 commits.

I know I can achieve this by first applying the patch, then doing an interactive add (hunk by hunk), like so:

git apply mypatch
git add -p

I was just wondering if it's possible to do that in one git command. I found nothing in the manpages of git apply, nor in git add.

EDIT

I don't think this question should be considered as a duplicate of Syntax for Git aliases with multiple commands as that question (and its answer) does not need does not involve a parameter passed to the alias.

3

There are 3 best solutions below

0
On BEST ANSWER

I'm replying to my own question, thanks to the comment of @8bittree.

There are at least 2 ways to do that:

  • using a shell function (see 8bittree's answer)
  • using a git alias. I prefer this solution as it only involves .gitconfig, no need to modify .bashrc, and git shell completion works for the new alias, it is shown alongside other standard git commands in the completion list

So this is what I ended to add to my global .gitconfig:

[alias]
    # interactive apply patch
    ipatch = "!f() { git apply $1; git add -p; }; f"

I then just have to do:

git ipatch mypatchfile
0
On

As mentioned in my comment, you can get a similar effect with a function. After some more thought, I'm not sure if an alias would work, since you need to specify the patch file and possibly some options. Here's an example function you could add to your .bashrc, you may have to adjust if you use a shell other than Bash. I think it should work with Zsh, and maybe Ksh, but I have not tested it with those.

function git() {
    # Allows you to call `git ipatch patchfile`
    # Change ipatch to whatever you want the git command to be
    if [[ "$1" = ipatch ]]; then
        shift
        # Specify the full path to git, otherwise infinite recursion
        # Alternatively, name the function something else
        /usr/bin/git apply "$@"
        /usr/bin/git add -p
    else
        /usr/bin/git "$@"
    fi
}

If you want to add more custom git commands, it may be worth looking into a case statement, rather than a long chain of ifs.

1
On

You can use the unix "patch" command (separate from git). That way Git will not know anything about the 'patch' --- Git will just think you did regular editing. Output of "git show" and "git diff" is compatible with the unix "patch" command:

# assuming "my-git-repo" is clean...
cd my-git-repo
patch -p1 < my.patch
git status

At this point you can use "git add" / "git commit" to create the sequence of commits you want.