248

Is it even possible?

Basically, there's a remote repository from which I pull using just:

git pull

Now, I'd like to preview what this pull would change (a diff) without touching anything on my side. The reason is that thing I'm pulling might not be "good" and I want someone else to fix it before making my repository "dirty".

João Melo
  • 784
  • 6
  • 16
Milan Babuškov
  • 59,775
  • 49
  • 126
  • 179
  • 4
    Your edit is weird. Doing a "git fetch" doesn't alter your working tree in any way, so it doesn't matter if you have uncommitted local changes. And it's unclear whay part of the fetch you want to undo, since it doesn't touch your work tree. – dkagedal Oct 08 '08 at 19:42
  • Thanks dkagedal, I wrote this before I fully understood how Git works. I removed that edit. – Milan Babuškov Jan 08 '10 at 02:12
  • 2
    Everyone (including the OP) resorted to that 'git fetch' is what you want. But what if you take the question word by word. For example you want to avoid the fetch for quirky reasons, like a write protected disk, or a risk of running out of disc space? Eg. a messed up repo that might send you several GB of data... – Kjell Jan 31 '21 at 22:59
  • I realize this is an old question, but the title is confusing, particularly "without doing fetch". I think when this was written there was an assumption made about *fetch* that turned out to be incorrect. Might it make sense to edit the question title now? (I'd propose simply removing "without doing fetch".) – TTT Jun 03 '21 at 22:22

10 Answers10

289

After doing a git fetch, do a git log HEAD..origin/master to show the log entries between your last common commit and the origin's master branch. To show the diffs, use either git log -p HEAD..origin/master to show each patch, or git diff HEAD...origin/master (three dots not two) to show a single diff.

There normally isn't any need to undo a fetch, because doing a fetch only updates the remote branches and none of your branches. If you're not prepared to do a pull and merge in all the remote commits, you can use git cherry-pick to accept only the specific remote commits you want. Later, when you're ready to get everything, a git pull will merge in the rest of the commits.

Update: I'm not entirely sure why you want to avoid the use of git fetch. All git fetch does is update your local copy of the remote branches. This local copy doesn't have anything to do with any of your branches, and it doesn't have anything to do with uncommitted local changes. I have heard of people who run git fetch in a cron job because it's so safe. (I wouldn't normally recommend doing that, though.)

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • I guess I missed that part of 'nothing to do with MY branches' while reading the docs. Thanks. – Milan Babuškov Oct 08 '08 at 19:38
  • 1
    For some reason that doesn't work for me. I tried git diff HEAD...origin/master and it didn't list any changes yet when i do 'pull origin master' it fetches and merges the changes. Is that because I set up the remote repository using git remote add? – screenm0nkey Sep 30 '11 at 14:43
  • @screenm0nkey: I don't know (without knowing more information). I recommend opening a new question to ask about this if you're still not sure. – Greg Hewgill Sep 30 '11 at 18:46
  • 1
    What works for me (after the git fetch): git log origin/master – slaman Oct 28 '16 at 18:29
  • Neither git diff HEAD...origin or git log -p HEAD..origin return any results for me (and I know there are changes). git log origin/master shows all commits, including the ones that have not already been pulled. – Rooster242 Feb 18 '19 at 23:41
  • @Rooster242: Try `git diff HEAD..origin/master`. I'll fix the answer to clarify. – Greg Hewgill Feb 18 '19 at 23:53
  • I work in an environment where the 'git fetch' latency is bad; I want to run 'git pull' without fetching sometimes ... because there's no reason for it since I just ran it. (I think git should track a 'fetch-freshness' value and only fetch when needed). – qneill Mar 28 '19 at 01:07
  • @qneill: If that's the case, then you just want to run `git merge` with what you have already fetched. See [What is the difference between 'git pull' and 'git fetch'?](https://stackoverflow.com/questions/292357/what-is-the-difference-between-git-pull-and-git-fetch) – Greg Hewgill Mar 28 '19 at 01:10
  • @GregHewgill yes that is true, very familiar, my comment was phrased poorly - I want the mechanism to suppress fetches for N minutes and decide between 'pull' v 'merge' for me. Time to work on a new git alias "pullnow" that will check the remote ref timestamp for me :) – qneill May 03 '19 at 05:29
  • 2
    `git diff ...@{u}` is the same as `git diff HEAD...origin/master` if origin/master is the upstream branch – cambunctious Jul 19 '19 at 14:58
  • Use git log --oneline HEAD..origin/$(git rev-parse --abbrev-ref HEAD) list in one line and no need to copy name of the branch – galsi Mar 16 '20 at 05:47
  • What happens when a remote 'bad' commit gets removed, after you have fetched it into your local repository so you can actually do the diff to show what the 'bad' commit would do ? How do i clean up the fetched data on local repo in such a case? – Torsten Apr 03 '21 at 17:34
  • I don't know if it's due to a recent upgrade in git, but for me `git diff main...origin/main` (three dots) returns nothing. On the other hand, both `git diff main..origin/main` (two dots) and `git diff main origin/main` (just a space) works as expected. And with `git log` is exactly the opposite: it only works as expected with three dots (or with a space). – kaiserlautern Jun 03 '22 at 11:23
53

I think git fetch is what your looking for.

It will pull the changes and objects without committing them to your local repo's index.

They can be merged later with git merge.

Man Page

Edit: Further Explination

Straight from the Git- SVN Crash Course link

Now, how do you get any new changes from a remote repository? You fetch them:

git fetch http://host.xz/path/to/repo.git/ 

At this point they are in your repository and you can examine them using:

git log origin 

You can also diff the changes. You can also use git log HEAD..origin to see just the changes you don't have in your branch. Then if would like to merge them - just do:

git merge origin

Note that if you don't specify a branch to fetch, it will conveniently default to the tracking remote.

Reading the man page is honestly going to give you the best understanding of options and how to use it.

I'm just trying to do this by examples and memory, I don't currently have a box to test out on. You should look at:

git log -p //log with diff

A fetch can be undone with git reset --hard (link) , however all uncommitted changes in your tree will be lost as well as the changes you've fetched.

Brian Gianforcaro
  • 26,564
  • 11
  • 58
  • 77
25

You can fetch from a remote repo, see the differences and then pull or merge.

This is an example for a remote repo called origin and a branch called master tracking the remote branch origin/master:

git checkout master                                                  
git fetch                                        
git diff origin/master
git pull --rebase origin master
Antonio Bardazzi
  • 2,996
  • 1
  • 23
  • 20
12

I created a custom git alias to do that for me:

alias.changes=!git log --name-status HEAD..

with that you can do this:

$git fetch
$git changes origin

This will get you a nice and easy way to preview changes before doing a merge.

mxk
  • 43,056
  • 28
  • 105
  • 132
5

I may be late to the party, but this is something which bugged me for too long. In my experience, I would rather want to see which changes are pending than update my working copy and deal with those changes.

This goes in the ~/.gitconfig file:

[alias]
    diffpull = !git fetch && git diff HEAD..@{u}

It fetches the current branch, then does a diff between the working copy and this fetched branch. So you should only see the changes that would come with git pull.

Michael
  • 8,362
  • 6
  • 61
  • 88
Andy P
  • 306
  • 4
  • 10
  • This is a well done alias, but I’m not sure why you’d want to do this in the first place. You’re going to have to deal with the changes sometime, right? You should be able to abort the merge part of `git pull` if you don’t like what it’s doing...so I’m not sure what the use case for this is. – Marnen Laibow-Koser Mar 18 '19 at 15:10
  • I know I have to deal with the changes at some point, but as I wrote, sometimes I don't want to. I just want to know if something is going to break and I have to reserve some more time for this - or if I can just do a `git pull` afterwards. Also I think thats what op's question was about. – Andy P Mar 19 '19 at 11:20
4

I use these two commands and I can see the files to change.

  1. First executing git fetch, it gives output like this (part of output):

    ...
    72f8433..c8af041  develop -> origin/develop
    ...

This operation gives us two commit IDs, first is the old one, and second will be the new.

  1. Then compare these two commits using git diff

    git diff 72f8433..c8af041 | grep "diff --git"

This command will list the files that will be updated:

diff --git a/app/controller/xxxx.php b/app/controller/xxxx.php
diff --git a/app/view/yyyy.php b/app/view/yyyy.php

For example app/controller/xxxx.php and app/view/yyyy.php will be updated.

Comparing two commits using git diff prints all updated files with changed lines, but with grep it searches and gets only the lines contains diff --git from output.

cowboycb
  • 539
  • 5
  • 11
1

This useful commands below I picked from this link https://gist.github.com/jtdp/5443297. Thanks to https://gist.github.com/jtdp

git fetch origin

# show commit logs of changes
git log master..origin/master

# show diffs of changes
git diff master..origin/master

# apply the changes by merge..
git merge origin/master

# .. or just pull the changes
git pull
SuperNova
  • 25,512
  • 7
  • 93
  • 64
0

If you don't want git-fetch to update your local .git, just copy your local repo to a temp dir and do a pull there. Here is a shor-hand:

$ alias gtp="tar -c . | (cd /tmp && mkdir tp && cd tp && tar -x && git pull; rm -rf /tmp/tp)"

Ex.:

$ git status
# On branch master
nothing to commit (working directory clean)

$ gtp
remote: Finding sources: 100% (25/25)
remote: Total 25 (delta 10), reused 25 (delta 10)
Unpacking objects: 100% (25/25), done.
From ssh://my.git.domain/reapO
   32d61dc..05287d6  master     -> origin/master
Updating 32d61dc..05287d6
Fast-forward
 subdir/some.file       |    2 +-
 .../somepath/by.tes    |    3 ++-
 .../somepath/data      |   11 +++++++++++
 3 files changed, 14 insertions(+), 2 deletions(-)

$ git status
# On branch master
nothing to commit (working directory clean)

$ git fetch
remote: Finding sources: 100% (25/25)
remote: Total 25 (delta 10), reused 25 (delta 10)
Unpacking objects: 100% (25/25), done.
From ssh://my.git.domain/reapO
   32d61dc..05287d6  master     -> origin/master

$ git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.
#
nothing to commit (working directory clean)
AXE Labs
  • 4,051
  • 4
  • 29
  • 29
0

13 years later, you now have With a prefetch task in "git maintenance"(man)

The prefetch task updates the object directory with the latest objects from all registered remotes.

For each remote, a git fetch command is run.
The refmap is custom to avoid updating local or remote branches (those in refs/heads or refs/remotes).
Instead, the remote refs are stored in refs/prefetch/<remote>/.
Also, tags are not updated.

This is done to avoid disrupting the remote-tracking branches.
The end users expect these refs to stay unmoved unless they initiate a fetch.

With prefetch task, however, the objects necessary to complete a later real fetch would already be obtained, so the real fetch would go faster.
In the ideal case, it will just become an update to a bunch of remote-tracking branches without any object transfer.

And you can also do, since Git 2.32 (Q2 2021) a git fetch --prefetch, again without modifying your last fetch state.

See commit 32f6788, commit cfd781e, commit 2e03115 (16 Apr 2021), and commit a039a1f (06 Apr 2021) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit d250f90, 30 Apr 2021)

fetch: add --prefetch option

Helped-by: Tom Saeger
Helped-by: Ramsay Jones
Signed-off-by: Derrick Stolee

The --prefetch option will be used by the 'prefetch' maintenance task instead of sending refspecs explicitly across the command-line.
The intention is to modify the refspec to place all results in refs/prefetch/ instead of anywhere else.

Create helper method filter_prefetch_refspec() to modify a given refspec to fit the rules expected of the prefetch task:

  • Negative refspecs are preserved.
  • Refspecs without a destination are removed.
  • Refspecs whose source starts with "refs/tags/" are removed.
  • Other refspecs are placed within "refs/prefetch/".

Finally, we add the 'force' option to ensure that prefetch refs are replaced as necessary.

There are some interesting cases that are worth testing.

An earlier version of this change dropped the "i--" from the loop that deletes a refspec item and shifts the remaining entries down.
This allowed some refspecs to not be modified.
The subtle part about the first --prefetch test is that the refs/tags/* refspec appears directly before the refs/heads/bogus/* refspec.
Without that "i--", this ordering would remove the "refs/tags/*" refspec and leave the last one unmodified, placing the result in "refs/heads/*".

It is possible to have an empty refspec.
This is typically the case for remotes other than the origin, where users want to fetch a specific tag or branch.
To correctly test this case, we need to further remove the upstream remote for the local branch.
Thus, we are testing a refspec that will be deleted, leaving nothing to fetch.

fetch-options now includes in its man page:

--prefetch

Modify the configured refspec to place all refs into the refs/prefetch/ namespace.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
-3

What about cloning the repo elsewhere, and doing git log on both the real checkout and the fresh clone to see if you got the same thing.

Ed Greenberg
  • 209
  • 3
  • 12
  • A local copy is better reflective of the state than another clone. [See my main post for details](https://stackoverflow.com/a/59737915/632827). – AXE Labs Jan 14 '20 at 17:19