* how git pull works?
@ 2010-11-19 15:15 Dowlin Yang
2010-11-19 15:27 ` Dowlin Yang
2010-11-19 21:27 ` Jan Hudec
0 siblings, 2 replies; 4+ messages in thread
From: Dowlin Yang @ 2010-11-19 15:15 UTC (permalink / raw)
To: git
Hello
I sent an email earlier but it seems rejected. I resent again with plain text format. I am sorry for any inconvenience if you receive my messages twice, and please read the new one.
We have been using git for a while and it always works like a magic. We have several teammates and each of us may work on one or multiple branches at the same time. Sometimes one person may have to merge another's branch for getting the latest version. We always use git pull origin branch-name to get the remote branch merged and it always works nicely until recently we face a problem that we cannot figure it out. The following is the scenario we faced.
Suppose A had a branch b1 and B had a branch b2. They work on their own branch separately but b1 and b2 share the same file f1. Suppose A made a few changes to f1 on Nov 5th. Here are A's changes:
======= In branch b1, changes that were made by A on Nov 5th
@@ -1,6 +1,6 @@
<?
$COMMON_JS = array(
- 'lib/jquery-1.3.2.min.js'
,
+ 'lib/jquery-1.4.3.min.js',
'lib/jquery-ui-1.7.2.
custom.min.js',
'lib/jquery.metadata.js',
'lib/jquery.form.js',
@@ -26,6 +26,7 @@ $JS = array(
'files' => array(
'com/categories.js',
'com/searcher.js',
+ 'com/category_
bar.js',
'com/query_refiner.js',
'com/fast_input.
js',
'com/subscribe_form.js',
@@ -50,6 +51,7 @@ $JS = array(
'files' => array(
'com/categories.js',
'com/searcher.js',
+ 'com/category_
bar.js',
'com/product_image_loader.js',
'com/tab_toggle.
js',
'page.deal.js'
=======
A removed one line and added a few lines to f1 and then committed on Nov 5th. On the other hand, B made a few changes to f1 too on the next day Nov 6th. Here are B's changes:
======= In branch b2, changes that were made by B on Nov 6th
@@ -26,7 +26,6 @@ $JS = array(
'files' => array(
'com/categories.js',
'com/searcher.js',
- 'com/category_
bar.js',
'com/query_refiner.js',
'com/fast_input.
js',
'com/subscribe_form.js',
@@ -51,7 +50,6 @@ $JS = array(
'files' => array(
'com/categories.js',
'com/searcher.js',
- 'com/category_
bar.js',
'com/product_image_loader.js',
'com/tab_toggle.
js',
'page.deal.js'
=======
B removed a few lines and then committed on Nov 6th. They kept updating other files in the following days. After a few days, we decide to merge A's branch b1 with B's branch b2. So A did git pull origin b2 in b1, and the expected resultant file is sth like this:
======== Expected resultant file
$COMMON_JS = array(
- 'lib/jquery-1.3.2.min.js',
+ 'lib/jquery-1.4.3.min.js'
,
'lib/jquery-ui-1.7.2.custom.min.js',
'lib/jquery.metadata.js',
'lib/jquery.form.js',
.....
'files' => array(
'com/categories.js',
'com/searcher.js'
,
- 'com/category_bar.js',
'com/query_
refiner.js',
'com/fast_input.js',
'com/subscribe_
form.js',
.....
'files' => array(
'com/categories.js',
'com/searcher.js'
,
- 'com/category_bar.js',
'com/product_
image_loader.js',
'com/tab_toggle.js',
'page.deal.js'
========
We expect com/category_bar.js will be removed and lib/jquery-1.3.2.min.js will be replaced by lib/jquery-1.4.3.min.js However, it did not work like we expected. Instead, com/category_bar.js are still there, and jquery is replaced. We wonder why it works like this. Aren't newer changes supposed to be applied? Why older changes are the final results? Perhaps we misunderstand git pull? Please enlighten us where we may make any mistake. Else we just feel like we cannot trust git pull. :(
Oh, I forgot to mention one thing in the above scenario. B's b2 branch had com/category_bar.js added earlier than A's b1. A manually added the same changes to b1 on Nov 5th, but later B decided to remove com/category_bar.js from b2 on Nov 6h as I described.
So, is it possible that git assumes com/category_bar.js are added twice and removed once, so it means the final result will be com/category_bar.js is added once? It is not easy to describe the scenario... Any help is appreciated! Thanks very much.
Huiting
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: how git pull works?
2010-11-19 15:15 how git pull works? Dowlin Yang
@ 2010-11-19 15:27 ` Dowlin Yang
2010-11-19 21:27 ` Jan Hudec
1 sibling, 0 replies; 4+ messages in thread
From: Dowlin Yang @ 2010-11-19 15:27 UTC (permalink / raw)
To: git
Oops, the above lines are wrongly aligned. How can I fix them?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: how git pull works?
2010-11-19 15:15 how git pull works? Dowlin Yang
2010-11-19 15:27 ` Dowlin Yang
@ 2010-11-19 21:27 ` Jan Hudec
2010-11-20 1:18 ` Dowlin Yang
1 sibling, 1 reply; 4+ messages in thread
From: Jan Hudec @ 2010-11-19 21:27 UTC (permalink / raw)
To: Dowlin Yang; +Cc: git
On Fri, Nov 19, 2010 at 23:15:51 +0800, Dowlin Yang wrote:
> I sent an email earlier but it seems rejected. I resent again with plain
> text format. I am sorry for any inconvenience if you receive my messages
> twice, and please read the new one.
If it was HTML it was rejected by the list software and nobody ever saw it.
HTML is not accepted by any of the lists on vger.kernel.org.
> Suppose A had a branch b1 and B had a branch b2. They work on their own
> branch separately but b1 and b2 share the same file f1. Suppose A made
> a few changes to f1 on Nov 5th.
Dates are irrelevant. What is the most recent common ancestor?
Note, that most recent common ancestor is such commit, that is reachable from
both branches ("common ancestor") and it is not reachable from any other
common ancestor ("most recent"). No mention of dates anywhere -- just
parent-child relation between commits.
> Here are A's changes:
> [snip]
> A removed one line and added a few lines to f1 and then committed on Nov
> 5th.
>
> On the other hand, B made a few changes to f1 too on the next day Nov 6th.
> Here are B's changes:
> [snip]
> B removed a few lines and then committed on Nov 6th.
>
> They kept updating other files in the following days. After a few days, we
> decide to merge A's branch b1 with B's branch b2. So A did git pull origin
> b2 in b1, and the expected resultant file is sth like this:
> [snip]
Now git -- and for that matter any other version control system out there
that ever had a merge command -- looks for the most recent common ancestor.
Let's call it 'a'(1).
Now git applied both changes from a to b1 and changes from a to b2. It uses
the 3-way merge algorithm, which is basically:
- match up all lines that are the same in all three versions
- for lines where a and b1 is the same, take b2
- for lines where a and b2 is the same, take b1
- for lines where b1 and b2 are the same, take b1 (== b2)
- for lines where a, b1 and b2 all differ, declare conflict
You can equally think about this algorithm as applying diff from a to b1 to
b2 or applying diff from a to b2 to b1. All should give the same results(2).
For adding/removing files, just think of the tree as file listing what files
are included (where order is ignored, so the same name is always matched up).
The individual changes are not considered, ever. Only the sum of changes
since most recent common ancestor on one and the other side.
> Aren't newer changes supposed to be applied? Why older changes are the
> final results?
No. All changes since branch point or last merge are applied.
> B's b2 branch had com/category_bar.js added earlier than A's b1. A manually
> added the same changes to b1 on Nov 5th, but later B decided to remove
> com/category_bar.js from b2 on Nov 6h as I described.
b2 had category_bar.js added and removed again, so in the end it had no
changes in category_bar.js
b1 had category_bar.js added
No change (between a and b2) versus addition (between a and b1) is addition.
So category_bar.js is added in the result.
If you didn't add category_bar.js independently on b1, but instead pulled
from b2, the pulled revision would have been most recent common ancestor, so
b1 would see no further change and b2 would see deletion and result would be
deletion.
Footnotes:
~~~~~~~~~~
1) You can query most recent common ancestor with 'git merge-base b1 b2'.
You can view/list all commits from common ancestor to b2 with 'b1..b2'
refspec to gitk/git log. You can view/list all commits from common
ancestor to both b1 and b2 with 'b1...b2' refspec to gitk/git log. You can
get the cumulative diff from common ancestor to b2 with 'git diff
b1...b2'.
2) Unless there are conflicts or a repeated text, in which case patch
application (with limited context) would not have enough information on
where to apply while 3-way merge would.
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: how git pull works?
2010-11-19 21:27 ` Jan Hudec
@ 2010-11-20 1:18 ` Dowlin Yang
0 siblings, 0 replies; 4+ messages in thread
From: Dowlin Yang @ 2010-11-20 1:18 UTC (permalink / raw)
To: Jan Hudec; +Cc: git
Hi Bulb
Now I totally got it. Thanks very much for the explanation!
Huiting
On Nov 20, 2010, at 5:27 AM, Jan Hudec wrote:
> On Fri, Nov 19, 2010 at 23:15:51 +0800, Dowlin Yang wrote:
>> I sent an email earlier but it seems rejected. I resent again with plain
>> text format. I am sorry for any inconvenience if you receive my messages
>> twice, and please read the new one.
>
> If it was HTML it was rejected by the list software and nobody ever saw it.
> HTML is not accepted by any of the lists on vger.kernel.org.
>
>> Suppose A had a branch b1 and B had a branch b2. They work on their own
>> branch separately but b1 and b2 share the same file f1. Suppose A made
>> a few changes to f1 on Nov 5th.
>
> Dates are irrelevant. What is the most recent common ancestor?
>
> Note, that most recent common ancestor is such commit, that is reachable from
> both branches ("common ancestor") and it is not reachable from any other
> common ancestor ("most recent"). No mention of dates anywhere -- just
> parent-child relation between commits.
>
>> Here are A's changes:
>> [snip]
>> A removed one line and added a few lines to f1 and then committed on Nov
>> 5th.
>>
>> On the other hand, B made a few changes to f1 too on the next day Nov 6th.
>> Here are B's changes:
>> [snip]
>> B removed a few lines and then committed on Nov 6th.
>>
>> They kept updating other files in the following days. After a few days, we
>> decide to merge A's branch b1 with B's branch b2. So A did git pull origin
>> b2 in b1, and the expected resultant file is sth like this:
>> [snip]
>
> Now git -- and for that matter any other version control system out there
> that ever had a merge command -- looks for the most recent common ancestor.
> Let's call it 'a'(1).
>
> Now git applied both changes from a to b1 and changes from a to b2. It uses
> the 3-way merge algorithm, which is basically:
> - match up all lines that are the same in all three versions
> - for lines where a and b1 is the same, take b2
> - for lines where a and b2 is the same, take b1
> - for lines where b1 and b2 are the same, take b1 (== b2)
> - for lines where a, b1 and b2 all differ, declare conflict
>
> You can equally think about this algorithm as applying diff from a to b1 to
> b2 or applying diff from a to b2 to b1. All should give the same results(2).
>
> For adding/removing files, just think of the tree as file listing what files
> are included (where order is ignored, so the same name is always matched up).
>
> The individual changes are not considered, ever. Only the sum of changes
> since most recent common ancestor on one and the other side.
>
>> Aren't newer changes supposed to be applied? Why older changes are the
>> final results?
>
> No. All changes since branch point or last merge are applied.
>
>> B's b2 branch had com/category_bar.js added earlier than A's b1. A manually
>> added the same changes to b1 on Nov 5th, but later B decided to remove
>> com/category_bar.js from b2 on Nov 6h as I described.
>
> b2 had category_bar.js added and removed again, so in the end it had no
> changes in category_bar.js
>
> b1 had category_bar.js added
>
> No change (between a and b2) versus addition (between a and b1) is addition.
> So category_bar.js is added in the result.
>
> If you didn't add category_bar.js independently on b1, but instead pulled
> from b2, the pulled revision would have been most recent common ancestor, so
> b1 would see no further change and b2 would see deletion and result would be
> deletion.
>
> Footnotes:
> ~~~~~~~~~~
> 1) You can query most recent common ancestor with 'git merge-base b1 b2'.
> You can view/list all commits from common ancestor to b2 with 'b1..b2'
> refspec to gitk/git log. You can view/list all commits from common
> ancestor to both b1 and b2 with 'b1...b2' refspec to gitk/git log. You can
> get the cumulative diff from common ancestor to b2 with 'git diff
> b1...b2'.
>
> 2) Unless there are conflicts or a repeated text, in which case patch
> application (with limited context) would not have enough information on
> where to apply while 3-way merge would.
>
> --
> Jan 'Bulb' Hudec <bulb@ucw.cz>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-11-20 1:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-19 15:15 how git pull works? Dowlin Yang
2010-11-19 15:27 ` Dowlin Yang
2010-11-19 21:27 ` Jan Hudec
2010-11-20 1:18 ` Dowlin Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).