292

How can we get the difference between two git repositories?

The scenario: We have a repo_a and repo_b. The latter was created as a copy of repo_a. There have been parallel development in both the repositories afterwards. Is there a way we can list the differences of the current versions of these two repositories?

jww
  • 97,681
  • 90
  • 411
  • 885
sanjayav
  • 4,896
  • 9
  • 32
  • 30

12 Answers12

337

In repo_a:

git remote add -f b path/to/repo_b.git
git remote update
git diff master remotes/b/master
git remote rm b
Geremia
  • 4,745
  • 37
  • 43
iamamac
  • 9,632
  • 4
  • 35
  • 30
  • I had to specify remotes/b/master as per the other answer: http://stackoverflow.com/a/4710379/284051 – Doug Moscrop Mar 27 '12 at 15:00
  • 6
    What if you need to compare repo_a/master with a specific tag of repo_b? – David Torres Oct 17 '14 at 16:39
  • 5
    not working for me, it's throwing: fatal: ambiguous argument 'remotes/b/master': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git [...] -- [...]' Any ideas here? – Andrew Heekin Sep 02 '15 at 03:09
  • 2
    I'm getting the same as @AndrewHeekin. Does anyone have a solution? – parliament Nov 06 '15 at 13:57
  • Actually I fixed it. Seems my check-in of the other remote failed so there was no code in the repo. After I added the code I had to re-add the remote (I'm sure I couldn't updated it without re-adding but I didnt know how) but it works now. thanks! – parliament Nov 06 '15 at 14:01
  • 1
    @parliament @AndrewHeekin: See my revision to the answer. You need to run `git remote update` before `diff`ing. – Geremia Feb 11 '16 at 17:21
  • 4
    I seem to need to specify `origin/master` rather than a bare `master`. Also, this finds the difference between the master branches, so what if you want to find all branches that are different? E.g. to check the status of a repository backup? – davidA Sep 12 '16 at 22:42
  • 7
    Can you explain what is doing every line? Thanks ! – Enrique Jun 16 '19 at 15:21
  • Just wondering, but `-f` (`git fetch b` after setting up the remote information) is doing less than `git remote update` (`git fetch` for each remote) - is there an additional reason for it being there? – fkarg Jun 19 '20 at 19:14
  • @DavidTorres, were you able to get your answer? – Nasif Imtiaz Ohi Jun 23 '21 at 00:58
  • 1
    @NasifImtiazOhi I don't recall... this was more than 6 years ago – David Torres Jun 25 '21 at 11:12
  • This is not working for me. Using `/path/to/local/directory` instead of `/path/to/repo_b.git` works initially but then after `git remote update` the `git diff` returns Andrew's "ambiguous argument" error. Using `githubusername/repo.git` gives `fatal: does not appear to be a git repository` – Caleb Stanford Dec 15 '21 at 21:30
  • Ah, figured it out! First line needs the full `https://` for the remote path: `git remote add -f b https://github.com/username/repo_b.git` – Caleb Stanford Dec 15 '21 at 21:32
  • Tried to edit but the suggested edit queue is full. – Caleb Stanford Dec 15 '21 at 21:33
  • simple and helpful, it works – Fuong Lee Jan 03 '23 at 03:30
68

Meld can compare directories:

meld directory1 directory2

Just use the directories of the two git repos and you will get a nice graphical comparison:

enter image description here

When you click on one of the blue items, you can see what changed.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
19

You can add other repo first as a remote to your current repo:

git remote add other_name PATH_TO_OTHER_REPO

then fetch brach from that remote:

git fetch other_name branch_name:branch_name

this creates that branch as a new branch in your current repo, then you can diff that branch with any of your branches, for example, to compare current branch against new branch(branch_name):

git diff branch_name
M.Kouchi
  • 800
  • 7
  • 12
11

I use PyCharm which has great capabilities to compare between folders and files.

Just open the parent folder for both repos and wait until it indexes. Then you can use right click on a folder or file and Compare to... and pick the corresponding folder / file on the other side.

It shows not only what files are different but also their content. Much easier than command line.

MrE
  • 19,584
  • 12
  • 87
  • 105
10

An easy way to do that without touching your remotes config. From repo A, in master (assume you want to compare master branches):

git fetch path/to/repo_b.git master
git diff FETCH_HEAD
jorisv92
  • 420
  • 4
  • 7
9

Once you have both branches in one repository you can do a git diff. And getting them in one repository is as easy as

git fetch /the/other/repo/.git refs/heads/*:refs/remotes/other/*
Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
  • Is there a way to cherry-pick history with a little change: For example in remote repo file is placed in one directory, but I want apply changes to same file but which is placed in different directory in local repo? – Eugen Konkov Feb 22 '17 at 11:18
  • If you're talking about a small change, I think the easiest would be just to make a diff and then reapply it to the other file using patch. – Michael Krelin - hacker Feb 22 '17 at 16:43
  • Patch is not applied because of different file names despite on those are same files – Eugen Konkov Feb 22 '17 at 16:52
  • Oh, I was only thinking of different directories, not file names (directories can be easily handled via patch options). Well, for the filenames I'd just change them manually or through the script. That said, I'm not saying there's no better solution, just what I can come up with without digging anywhere. – Michael Krelin - hacker Feb 22 '17 at 21:40
  • what if I want to compare all branches, though? – endolith Jul 16 '20 at 17:17
9
git diff master remotes/b

That's incorrect. remotes/b is a remote, but not a branch.

To get it to work, I had to do:

git diff master remotes/b/master
sra
  • 23,820
  • 7
  • 55
  • 89
James
  • 99
  • 1
  • 1
8

See http://git.or.cz/gitwiki/GitTips, section "How to compare two local repositories" in "General".

In short you are using GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable to have access to object database of the other repository, and using git rev-parse with --git-dir / GIT_DIR to convert symbolic name in other repository to SHA-1 identifier.

Modern version would look something like this (assuming that you are in 'repo_a'):

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo_b/.git/objects \
   git diff $(git --git-dir=../repo_b/.git rev-parse --verify HEAD) HEAD

where ../repo_b/.git is path to object database in repo_b (it would be repo_b.git if it were bare repository). Of course you can compare arbitrary versions, not only HEADs.


Note that if repo_a and repo_b are the same repository, it might make more sense to put both of them in the same repository, either using "git remote add -f ..." to create nickname(s) for repository for repeated updates, or obe off "git fetch ..."; as described in other responses.

skalee
  • 12,331
  • 6
  • 55
  • 57
Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
3

You can use the following command:

diff -x .git -r repo-A repo-B

or for the side by side you can use:

diff -x .git -W200 -y -r repo-A repo-B

In case of Colorizing every diff file, you can use:

diff -x .git -W200 -y -r repo-A repo-B | sed -e "s/\(^diff .*\)/\x1b[31m\1\x1b[0m/"
Gerard
  • 31
  • 5
1

Your best bet is to have both repos on your local machine and use the linux diff command with the two directories as parameters:

diff -r repo-A repo-B

Andrew Heekin
  • 671
  • 1
  • 6
  • 15
  • 3
    The only way to make this usable is to rename one of the .git directories. this reduces to two lines pages of differences that don't matter. Been there, done that, came here looking for a better answer. – hildred Oct 10 '16 at 22:02
1

To follow up @iamamac answer to have a nice summary after this:

git remote add -f b path/to/repo_b.git
git remote update

I would use diff-tree:

git diff-tree master remotes/b/master --compact-summary
Przemek Nowicki
  • 572
  • 4
  • 7
0

Reminder to self... fetch first, else the repository has not local hash (I guess).

step 1. Setup the upstream remote and above^

diffing a single file follows this pattern :

git diff localBranch uptreamBranch --spacepath/singlefile

git diff master upstream/nameofrepo -- src/index.js

Hillsie
  • 607
  • 1
  • 6
  • 15