Tom Jenkinson wrote on 12/ 7/18 02:34 AM:
Tom Jenkinson wrote on 12/6/18
1:49 PM:
Tom Jenkinson
wrote on 12/6/18 3:38 AM:
As soon as a commit in
your tree does not have
identical SHA to what is
in the main repo it won't
push cleanly.
I don't understand. How are two commits
considered to be "the same" if not by
their SHA?
If there's a commit in my repo that's
not in the remote, and there's a commit
in the remote, that's not in my repo, I
understand. But if I do a "pull -r",
how can there be a commit in the remote
that I don't have? Doesn't "pull -r"
pull down everything from the remote and
add my stuff on top of it, without
changing what it pulled down?
I tried to simulate it
a bit with creating two
branches using your
current master and then on
one of the branches doing
a "git commit --amend
--no-edit" so although
they are both functionally
identical both branches
have a different SHA for
the head commit.
"commit --amend" is effectively the same
as completely removing that commit and
replacing it with a new commit, right?
I understand how that would get things
out of sync, but I wasn't doing that.
git diff test2 (my
second branch) - shows no
differences
but if I do "git rebase
test2" it changes the
branch I am on to use the
SHA from the test2 branch.
History looks clean still
but it can't be clean
pushed.
If I do "git merge
test2" instead, it can be
pushed but history does
not look nice.
Here are the branches:
There reason they all
have different SHA is
because the second two
commits are in a different
order. If master was going
to have exactly the same
commits in the exact same
order you could have done
"git rebase EE4J_8" each
time and it should have
pulled in the lastest
commits without changing
their SHAs. In practice I
don't see how that would
have been possible over
time as at some point they
would diverge.
Whenever I try to sync
two branches I cherry-pick
commits from the branch
that is ahead onto the
other branch. That means
that history is not
re-written on the branch I
am cherry-picking to and
so I don't need to force
push.
So you're saying that rebase might
rewrite commits on the main branch, not
just add commits from the other branch?
Ouch!
How does it know which commits to
rewrite?
From what I know, it will rewrite
anything that is different, because you
diverged after
beab9265aa39a4c3c4a2e220b1e4c198060803a5
then anything after that would be changed.
I don't understand what you mean by "anything after
that would be changed".
Yes, the EE4J_8 branch forked from the master after
the first commit to the master.
If you do "git rebase EE4J_8" on master
it will be made to look like the EE4J_8
branch where the commits are the same.
I don't understand "made to look like".
I think this is the crucial thing, these two commits
are not the same:
When you do a rebase, then git will try to make them
the same (and in your case it is able to do that)
Yes, they're two completely different commits that happen to make
exactly the same change. How does git "make them the same"? Does
it throw away one of them because it does the same change as the
other one? Does it create a new commit that replaces the two
existing commits?
Git makes them the same in the following way - when you "git rebase EE4J_8" on master then you will see that 7be4f44afd920e35ede59aa06221cedc7b9bd12c will overwrite b21b640514fd66a198d87d4c7b096dcea4dbd7bc on that master branch (and the same happens for all the previous commits too).
Surely there must be a description of how this works somewhere in
the git documentation, right?... :-) (Although too much of the git
documentation is written for the people who implemented git, not the
people who use it, and thus is impenetrable.)
Although it seems to relate primarily to a different cautionary note, I think that the following is the closest to what is going on here:
I guess the bottom line here is that if people would stop making the
same change to both master and EE4J_8, we wouldn't have this
problem, right? Why isn't everyone just making the changes to
EE4J_8 and then merging or rebasing that on master?
I am not sure it is as straight forward as that. As soon as you a commit on master that isn't in EE4J_8 branch (and doesn't want to be) you will get this problem so at some point as a rebase.
The best way to deal with Git in my opinion is to put commits on to a feature branch first (probably for us it is the EE4J_8 branch at the moment) and then to "git cherry-pick" the ones you need to backport onto another branch (in our case master) - thus avoiding rebase and merge commands between branches. It does mean you have to expliciting know all the commits you are moving between the branches.
Personally I use rebasing when I am developing on my own fork of a branch so that I know that any commits I am offering for pull request will be able to be merged to the upstream version of that branch cleanly: "git pull --rebase --ff-only"