183

Today I was trying to use the git mergetool on the Windows command prompt and realized that it was defaulting to use Vim, which is cool, but I'd prefer VS Code.

How can I have Visual Studio Code function as my GUI for handling merge conflicts (or even as a diffing tool) for Git?

Is it possible to setup VS Code to get visuals for a three-way merge?

Eric D. Johnson
  • 10,219
  • 9
  • 39
  • 46

5 Answers5

354

Update: As of Visual Studio Code 1.70 Three-way merge with improvements were added. Visuals and further explanations are available if that's of interest to you .

As of Visual Studio Code 1.13 Better Merge was integrated into the core of Visual Studio Code.

The way to wire them together is to modify your .gitconfig and you have two options.

  1. To do this with command line entries, enter each of these: (Note: if on Windows Command Prompt replace ' with ". Thanks to Iztok Delfin and e4rache for helping clarify this.)

    1. git config --global merge.tool vscode
    2. git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'
    3. git config --global diff.tool vscode
    4. git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
  2. To do this by pasting some line in the .gitconfig with Visual Studio Code.

    • Run git config --global core.editor 'code --wait' from the command line.

    • From here you can enter the command git config --global -e. You will want to paste in the code in the "Extra Block" below.

        [user]
            name = EricDJohnson
            email = cool-email@neat.org
        [gui]
            recentrepo = E:/src/gitlab/App-Custom/Some-App
        # Comment: You just added this via 'git config --global core.editor "code --wait"'
        [core]
            editor = code --wait
        # Comment: Start of "Extra Block"
        # Comment: This is to unlock Visual Studio Code as your Git diff and Git merge tool
        [merge]
            tool = vscode
        [mergetool "vscode"]
        # Comment: Original way before three-way merge shown commented out
        #    cmd = code --wait $MERGED
        # Comment: For "Three-way merge"
            cmd = code --wait --merge $REMOTE $LOCAL $BASE $MERGED
        [diff]
            tool = vscode
        [difftool "vscode"]
            cmd = code --wait --diff $LOCAL $REMOTE
        # Comment: End of "Extra Block"
      

Now from within your Git directory with a conflict run git mergetool and, tada, you have Visual Studio Code helping you handle the merge conflict! (Just make sure to save your file before closing Visual Studio Code.)

Accept Incoming Change anyone?

For further reading on launching code from the command line, look in this documentation.

For more information in git mergetool check out this documentation.

Eric D. Johnson
  • 10,219
  • 9
  • 39
  • 46
  • 1
    Does this integration of Better Merge allow you to accept and choose which portion to merge? Or do you still have to remove by hand the extra comments of the conflict like `<<<< HEAD` and `>>>> develop`? – ghiscoding Aug 29 '17 at 19:22
  • 3
    There is a line above <<<< Head, that gets inserted that lists the options: "Accept Current Change | Accept Incoming Change | Accept Both Changes | Compare Changes" and I believe it inserts this on each section of detected changes in the file. But within a section if you want to custom merge a bit of this and a bit of that by hand, I believe you would make that change in your local and then go with the "Accept Current Change" option. So the work flow does kind of have you take a step back in order to take a step forward. If others resolve this in a different way please post here to educate us – Eric D. Johnson Aug 30 '17 at 20:03
  • 1
    Oh I see it in your print screen now, very neat. Thanks a lot for the explanation and the how to do it. Will happily use it on the next time conflicts gets in the way :) – ghiscoding Aug 30 '17 at 23:31
  • @FiruzzZ , good question, `vscode` is just a variable name you pick, on the lines like `tool = vscode` and then reference again in quotes below that in `[mergetool "vscode"]` . So you could use `tool = vs-code-beats-chuck-norris` and then `[mergetool "vs-code-beats-chuck-norris"]` and it should still work. – Eric D. Johnson Aug 06 '18 at 18:56
  • 5
    I get the error `unknown tool: vscode`... I'm pretty sure to call VsCode from command line you have to use `code` instead of `vscode` – Kellen Stuart Sep 05 '18 at 16:02
  • @KolobCanyon just for clarity for you and others who might hit the same wall, in `cmd = code --wait $MERGED` , you are correct, you need to use "code", but in the reference lines above (`tool = vscode` and `[mergetool "vscode"]`) you can pick the variable name, like was mentioned above in the reply to @FiruzzZ . – Eric D. Johnson Sep 05 '18 at 18:36
  • @EricD.Johnson I re-read your answer and there is no reference to setting the alias `code => vscode`. You should probably just use `code` as it would make things easier. – Kellen Stuart Oct 02 '18 at 22:26
  • 28
    Also, this is not working for me. It just pops open VsCode and no files are ever brought up – Kellen Stuart Oct 02 '18 at 22:35
  • @KolobCanyon if you open a new question ( and link it in a comment here) with what's in your `.gitconfig` we can try to do a little collaborative debugging and see if we can figure it out. Far warning I don't currently have hardware running macOS, but since you're a PowerShell nerd I'm guessing you're rocking Windows as well. – Eric D. Johnson Oct 03 '18 at 21:16
  • Is there a way to let git open all the diffs at once instead of waiting for you to close the current tab to open another? – Pluc Dec 06 '18 at 14:14
  • @Pluc I assume you mean when there are multiple rounds of resolving the merge across lots of commits? I don't think there is a way to do this at the moment. – Eric D. Johnson Dec 06 '18 at 16:00
  • 1
    What I would like to do is "giff difftool mybranch master" and have VS code open with the diff of all the files that changed. Right now, it would open only one and wait for you to close it. – Pluc Dec 17 '18 at 21:15
  • @Pluc if you open the folder your git project is in with VS Code and then the little branching git icon, it will show you all the changes list file by file in *SOURCE CONTROL: GIT* side panel (as well as STAGED changes). See https://code.visualstudio.com/Docs/editor/versioncontrol#_git-support for screenshots and more explanation. – Eric D. Johnson Dec 18 '18 at 19:59
  • 1
    Oh ya, I know that, but it does not have the flexibility I'm looking for like getting a diff between two commits or two branches. And if it does, navigating git in vs code is quite horrible in my opinion. I just like their diff and merge UI. I was going and saw the `git difftool -d` for a directory diff. I'll check how that works tomorrow. – Pluc Dec 19 '18 at 00:02
  • 1
    Although `git difftool -d` is pretty cool, VS code doesn't have a good way to diff two folders. The result is a VS code instance with a left and right folder but you need to manually select the matching left and right files, right click, compare. Not very practical. – Pluc Dec 19 '18 at 15:34
  • @Pluc sounds like you should try out extension https://marketplace.visualstudio.com/items?itemName=huizhou.githd . I tried it and it lets you do stuff like diff a folder in one branch against a different branch, etc. and move ahead one commit at a time to see how it morphs over time. Let us know if it gets you further down the path after you play around with it a bit. – Eric D. Johnson Dec 19 '18 at 16:17
  • 1
    there's @typo in code example on line 7 … it should be `[core]` instead of `[code]` (can't edit it so I writeing it as a comment) – iiic Mar 12 '19 at 14:44
  • 1
    Using Sublime Text in macos this worked for me. Just replaced _vscode_ and _code_ for _subl_. – Francisco Quintero Dec 18 '19 at 19:56
  • 1
    Note that you should also use single quotes when running the `git config` commands in PowerShell, otherwise the `$MERGED` and the other variables get replaced with empty strings before the command is executed. Single quotes tells PowerShell to treat it as a literal string and not to perform interpolation. – Josh Gallagher Mar 31 '20 at 08:30
  • if it opens in a new window everytime, just remove the "-n" option from the config file – Tiju John Sep 11 '20 at 09:41
  • And is there a way to use Visual Studio 2019 as difftool when using VS 2019 only? For example, I click on compare on History window in VS2019 and it opens up VS Code since that's the default difftool now. I only want to use VS Code as a difftool when I'm on command prompt... – yakya Jan 15 '21 at 10:13
  • 1
    @sotn I believe you can pick which difftool you want if you have multiple defined with `git difftool --tool={someNonDefault}`. See this [multiple-diff-tools answer](https://stackoverflow.com/questions/9032133/multiple-diff-tools/34954253#34954253) – Eric D. Johnson Jan 15 '21 at 17:19
  • See also: https://www.roboleary.net/vscode/2020/09/15/vscode-git.html – Gabriel Staples Oct 14 '21 at 21:49
  • @GabrielStaples that link does give good visuals to compare **VS Code** with **VIM** and **Nano** – Eric D. Johnson Oct 19 '21 at 14:17
  • 1
    Going down the first path, running the commands with `"` on mac didn't work. VSCode would open when typing `git difftool` but with no files to compare. I had to make sure the config file is composed properly using path 2: `git config --edit` and changing `cmd` line to `cmd = code --wait --diff $LOCAL $REMOTE` manually. It wasn't formed well using the command line entries in path 1. In my case, I didn't want `--global`. – Rafs Aug 18 '22 at 10:13
  • @RTD Can you try it again with single quotes and tell me what you get for path 1? An editor to the answer but I think the wording threw you off. Basically double quote is just for Windows Command Prompt, and everybody else uses single-quote. – Eric D. Johnson Aug 19 '22 at 15:44
  • @EricD.Johnson true, the wording confused me. With `"`, the variables are stored as blanks. With `'`, things are better. Thank you. – Rafs Aug 19 '22 at 16:10
  • 1
    @RTD I simplified the wording to be less confusing now. Thanks for commenting so we could know to clean that up ;) – Eric D. Johnson Aug 19 '22 at 16:48
34

I had to replace the double quotes with simple quotes:

  git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'

for it to work properly (with double quotes, $LOCAL and $REMOTE are replaced by their values).

This is needed if you are using Git Bash for Windows instead of Windows Command Prompt.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
e4rache
  • 341
  • 3
  • 4
  • 1
    Not for me. I just did this on Windows using the Command Prompt. Perhaps you're using something different? If so, I suggest adding which environment you're using so others with the same environment will know that they'll need to make this change. – Todesengel Aug 20 '18 at 21:04
  • 1
    @e4rache and @Iztok-Delfin what you have listed here is helpful content but you've accidentally made it an answer, when it's really a comment. I'm sure you ran into trouble because you didn't have the 50 point on SO to allow you to comment, which is kind of a site work flow problem that should maybe be looked into. Anyway, thanks for contributing, and I added your tip in my answer above. Thanks for helping those who come later and are using Git Bash `:^)` – Eric D. Johnson Aug 23 '18 at 21:12
  • @eric-d-johnson I totally meant to make a comment instead of a reply. ( sorry, I'm new to this site ) and btw I was using bash on linux. Is there a way to transorm this reply into a comment ? – e4rache Sep 04 '18 at 12:34
  • @e4rache I don't know a way to make it a comment, but perhaps a moderator will see this and give us some tips (hint, hint). If you had the 50 points, you could make a comment on the accepted answer, and delete this one, so once you become an SO rock-star with tons of points you can come back here and do whatever housekeeping makes you happy and brings back good memories of how it all started. – Eric D. Johnson Sep 05 '18 at 18:29
  • The original solution didn't work fully on Mac OS, but this one worked fine – Mohamed Ghonemi Oct 03 '19 at 08:13
  • 1
    @mohamedghonemi Good feedback. I updated the explanation at the top for macOS and Linux now to remember to use single quotes (`'`s). – Eric D. Johnson Jan 16 '20 at 20:30
25

On top of the excellent existing answer, you should open VS Code in a new window by adding -n to the command line.

So your git config --global --edit looks something like this.

[merge]
        tool = vscode
[mergetool "vscode"]
        cmd = code --new-window --wait $MERGED
[diff]
        tool = vscode
[difftool "vscode"]
        cmd = code --new-window --wait --diff $LOCAL $REMOTE                                                    
Captain Man
  • 6,997
  • 6
  • 48
  • 74
mvd
  • 2,596
  • 2
  • 33
  • 47
  • I used these settings, but when I do `git diff commit_id1 commit_id2`, it doesn't bring up a VS code editor window. It still defaults to the terminal. Am I using the wrong command? – user5965026 Dec 10 '21 at 13:33
  • @user5965026 have you tried `git diftool` instead of `git diff`? – mvd Dec 13 '21 at 15:29
  • 1
    Note: use `cmd = code --wait --merge $REMOTE $LOCAL $BASE $MERGED` if you have VSCode 1.7+ and want three-way merge UI. – Rafs Aug 18 '22 at 10:23
11

Using the manual you can find an interesting argument:

git difftool --help 
-x <command>, --extcmd=<command>
       Specify a custom command for viewing diffs.  git-difftool ignores the configured defaults and runs $command $LOCAL $REMOTE when this option is specified.
       Additionally, $BASE is set in the environment.

With this information you can easily use the following command without touching the git configuration:

git difftool -x "code --wait --diff" 

Similar question here

Gomino
  • 12,127
  • 4
  • 40
  • 49
4

In case if someone want to resolve it in Visual Studio, another option would be doing it through Visual Studio: Team Explorer -> click on Home icon => Settings button => expand Git section => click on Global Settings

enter image description here enter image description here enter image description here

Daniel B
  • 3,109
  • 2
  • 33
  • 42
  • 7
    Visual Studio is not equivalent to Visual Studio Code. The way settings like this are done are quite different. See https://stackoverflow.com/a/33798601 for the differences – jwd630 Jan 18 '20 at 21:00
  • 3
    @jwd630 I know VS code is different than VS. I had this issue in VS but couldn't find a solution for that so I though it would be better to post it in case someone is experincing this problem. No need to down-vote. – Daniel B Jan 18 '20 at 21:07
  • 4
    This is an answer to a completely different question for a different product. – Jörg W Mittag Jun 12 '21 at 09:46