Tom, thanks for having the patience to try to explain this to me!
    
    Since no one else has jumped into this conversation, I'm wondering
    if this is all just completely clear to everyone else and they don't
    understand why I'm so slow, or if everyone else is confused as
    well!  :-)
    
    More comments below...
    
    Tom Jenkinson wrote on 12/10/18 04:41 AM:
    
      
      
        
          
            
              
                
                
                  
                  
                     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).
                 
               
             
           
         
       
    
    It's this overwriting/changing of existing commits on the master
    that seems surprising to me, and that I haven't seen described
    anywhere.
I think it is this bit I quoted from the rebase doc that describes it: "abandoning
                    existing commits and creating new ones that are
                    similar but different" - it seems to cover the idea that the rebase would abandon b21b640514fd66a198d87d4c7b096dcea4dbd7bc and create the new one (from that branches perspective at least) of 7be4f44afd920e35ede59aa06221cedc7b9bd12c (I realise 7be4f44afd920e35ede59aa06221cedc7b9bd12c is not truly a new commit but it is new to master).
    
    
      
        
          
            
              
                
                  
                  
                  
                     
                      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: 
                  
                  
                 
               
             
           
         
       
    
    Right, and that's exactly what I expected.
    
    The examples in that link don't show any cases where existing
    commits on the master are changed.
    
    I do see that there's one part I've been ignoring.  The examples
    show "merging" the master and branch by "fast-forwarding" the
    branch.  I haven't been doing that.  I've just been abandoning the
    branch, and planning to delete it.
    
    I think the key to understanding the problem is the "patch-id" they
    talk about briefly.
    
    I managed to reproduce my problem locally.  With identical commits
    on master and the branch, the rebase replaced the commits on the
    master with commits from the branch.  That still seems like the
    wrong thing to me; it seems like it should always favor the commits
    on the master.
    
    If I follow that with "git pull --rebase", I end up with what I
    expect - the duplicate commits from the branch thrown away and the
    unique commits from the branch applied to the end of master.
 
When I do  git pull --rebase upstream EE4J_8 on your javamail master what I see is that the duplicate commits on master are thrown away and replaced with the ones from EE4J_8 branch, then the unique commits from master are appended. That branch would need to be force pushed as to git they look like new commits.
    
    
      
        
          
            
              
                
                  
                  
                   
                  
                     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. 
                  
                 
               
             
           
         
       
    
    By "doesn't want to be" do you mean because it duplicates a change
    on the EE4J_8 branch?
 
By that I simply mean a commit you have on master that you personally do not want on the EE4J_8 branch
 
    
    In the Basic Rebase case, there are commits on the master that
    aren't on the branch, and that doesn't cause any problem.
    
    
      
        
          
            
              
                
                  
                  
                  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.
                  
                 
               
             
           
         
       
    
    I was expecting that rebase was just like cherry-pick, except it
    picked them all.
 
In my experience it is not, it will rewrite history and hence a force push is the only way to push them back to the repo. 
    
    Is there a way to tell cherry-pick to "pick everything on the
    branch"?
This might work (at least it seens to for the current state of the branches):
for i in `git cherry master EE4J_8 | grep "+ " | cut -f 2 -d " "`; do git cherry-pick $i; done
    
    
      
        
          
            
              
                
                  
                  
                  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"
                  
                 
               
             
           
         
       
    
    I always use "git pull --rebase".  I don't understand what effect
    -ff-only has in this case.
 
Sorry, the ff-only is not used interpretted by git in my example and so it is as you have it, it means that my local commits must be fit cleanly on top of the remote upstream branch but that is what I want.