git fetch或pull前检查remote有哪些变化

http://stackoverflow.com/questions/4944376/how-to-check-real-git-diff-before-merging-from-remote-

Since this topic comes up frequently, and can be confusing without a bit of background on how git works, I thought I'd try to explain the simplest case possible, but with sufficient depth that newcomers will have enough of a handle on it to do additional research.

If you set up your git repository via a normal 'clone' and have the default refspecs, meaning that your remote is named 'origin' and you pull/fetch from the branch 'master', you may sometimes need to see what's in the remote repository before pulling it down.

Since the "git pull" does an automatic merge (unless there are conflicts), it can be nice to see what's "incoming" next. If you're not familiar with how git works, and how refspecs in particular are managed, this can be a bit non-intuitive.

Suppose someone makes a change in the remote repository (for sake of illustration, adding a line to the remote repository by committing a change and pushing it), and you type:

$ git diff origin/master

You probably won't see any changes; however if you do the following:

$ git fetch; git diff ..origin/master

you'll see the difference between what's been committed to your local git repository and what's in the remote repository. You will NOT see any changes which are in your local filesystem or staged in your index.

Ok, why do we do this? origin/master is a refspec (see man pages). In short, this is what we refer to in order to compare against, pull or fetch from, and push to. All of the following are functionally equivalent:

origin/master
remotes/origin/master
refs/remotes/origin/master

To begin to untangle this, just take a peek at your repository's .git directory structure. A typical layout looks like this:

.git/refs
.git/refs/heads
.git/refs/heads/master
.git/refs/remotes
.git/refs/remotes/origin
.git/refs/remotes/origin/HEAD
.git/refs/remotes/origin/master
.git/refs/tags

Look at .git/refs/remotes/origin/HEAD; in the default case it will point to the branch you use to pull from and push to. In my case, since I'm on master, the contents of this text file look like this:

ref: refs/remotes/origin/master

This tells me that the HEAD of my remote is identified by the refspec 'refs/remotes/origin/master'(which happens to have the aliases mentioned above).

This doesn't tell us much; what's the state of the remote repository? Look at the state of the remote master:

$ cat .git/refs/heads/master     
6d0fb0adfdfa5af861931bb06d34100b349f1d63

Ok, it's a SHA1 hash; probably a commit. How does it get put in this file? Well, whenever you do a pull or a fetch, this file is updated with the most recent commit from the remote which was pulled or fetched. This explains why we have to git fetch prior to performing the diff. Remember, git fetch just updates your local copy of a remote branch, but doesn't merge it with your working copy. It is completely safe. A git fetch; git merge is equivalent to a git pull.

Once you do the fetch, git will be able to see the most recent commit in the remote repository as of the time of the fetch.

You can use various combinations of specifiers to git to see your diffs as you desire (the following examples use the local working copy as the implicit first commit):

$ git diff remote/origin   
This shows the incoming remote additions as deletions; any additions in your local 
repository are shown as additions.

$ git diff ...remote/origin
Shows incoming remote additions as additions; the triple-dot excludes changes
committed to your local repository.

$ git diff ..remote/origin
Shows incoming remote additions as additions; the double-dot includes changes
committed to your local repository as deletions (since they are not yet pushed).

For info on ".." vs "..." see git help diff as well as the excellent documentation at git-scm revision selection: commit ranges Briefly, for the examples above, double-dot syntax shows all commits reachable from origin/master but not your working copy. Likewise, the triple-dot syntax shows all the commits reachable from either commit (implicit working copy, remote/origin) but not from both.

I'm going through this step by step because I'm fairly new to git and this is exactly the type of thing that had me confused... I'm sure that git experts can find flaws with the details... I just hope this answer bridges the gap for some people who find all the various posts a bit terse.

转载于:https://my.oschina.net/uniquejava/blog/496661

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值