lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Did I resolve this git issue correctly?


From: Vadim Zeitlin
Subject: Re: [lmi] Did I resolve this git issue correctly?
Date: Wed, 7 Dec 2016 15:09:29 +0100

On Wed, 7 Dec 2016 10:23:49 +0000 Greg Chicares <address@hidden> wrote:

GC> Vadim--I didn't notice that you had pushed this changeset:
GC>   http://lists.nongnu.org/archive/html/lmi-commits/2016-12/msg00008.html
GC> so of course I hadn't pulled it before committing some changes of my own;
GC> when I pushed them, I saw:
GC> 
GC> $git push
GC> Enter passphrase for key REDACTED: 
GC> To REDACTED [at-sign] git.sv.gnu.org:/srv/git/lmi.git
GC>  ! [rejected]        master -> master (fetch first)
GC> error: failed to push some refs to 'REDACTED [at-sign] 
git.sv.gnu.org:/srv/git/lmi.git'
GC> hint: Updates were rejected because the remote contains work that you do
GC> hint: not have locally. This is usually caused by another repository pushing
GC> hint: to the same ref. You may want to first integrate the remote changes
GC> hint: (e.g., 'git pull ...') before pushing again.
GC> hint: See the 'Note about fast-forwards' in 'git push --help' for details.

 Hi,

 This is perfectly normal and the hint message explains it well, I think.
Its advice about resolving the problem is, however, unfortunately
sub-optimal.

GC> I took that "hint" and did this:
GC> 
GC> $git pull
GC> Enter passphrase for key REDACTED: 
GC> remote: Counting objects: 9, done.
GC> remote: Compressing objects: 100% (6/6), done.
GC> remote: Total 6 (delta 4), reused 0 (delta 0)
GC> Unpacking objects: 100% (6/6), done.
GC> >From git.sv.gnu.org:/srv/git/lmi
GC>    802eb23..0778129  master     -> origin/master
GC> Merge made by the 'recursive' strategy.
GC>  Makefile.am  | 1 +
GC>  configure.ac | 3 ++-
GC>  2 files changed, 3 insertions(+), 1 deletion(-)
GC> 
GC> I was somewhat alarmed when the world's most sophisticated editor, nano,
GC> took over my screen,

 BTW, I don't know which editor do you prefer, but I strongly suggest doing
"git config core.editor" to set it or define GIT_EDITOR environment
variable (unless you really prefer nano...).

GC> ...and I'm somewhat surprised that they appear identical in 'git log'
GC> now after I pulled your changes and pushed mine. I had expected that
GC> git would have yanked my changes out and stuffed them back in with
GC> different sha1sums. But I guess instead it applied my changes and
GC> then generated commit 8f4029 above to merge them?

 Yes.

GC> I don't see where this did any harm, but did I handle it in the best way?

 You indeed didn't do any harm, but many people, me included, think that
this is not the best way to do things. If you'd just like a recipe for
doing what I consider to be the right thing to do, the next time you fail
to push something because your local branch is behind master, just do "git
pull --rebase" instead of "git pull". This will do exactly what you
expected to happen, i.e. it will "yank your changes", fast-forward your
local master to the remote master and then "stuff your changes back" (which
will change their SHA-1s, of course). If you don't like magic commands, you
can also do "git fetch" and "git rebase origin/master" manually: this is
basically what "git pull --rebase" does, but maybe two commands are more
clear than one.


 But I strongly suspect that you actually want to understand why is this
preferable instead of just being told what to do, so let me explain: the
important thing is that this will avoid a meaningless merge commit and the
history will remain linear, which is not the case now:

        % git log --oneline --graph -8 master
        *   8f40291 Merge branch 'master' of git.sv.gnu.org:/srv/git/lmi
        |\
        | * 0778129 Disable clang warnings about mismatched struct/class
        | * c1c9c1a Fix linking of mc_enum unit test when using autotools
        * | fd65f39 Improve rate-table accuracy
        * | 7721853 Test for CR and VT separately
        * | 4f35f0c Use extension '.rates' for rate tables; enforce coding 
rules for them
        * | eb8fbb6 Revert "Allow empty comments in rate tables"
        |/
        * 802eb23 Refactor for simplicity

 Of course, there is nothing wrong with having merges in git, but it's
better if they're intentional and have semantic meaning, i.e. correspond to
the integration of some feature (or series of bug fixes) into master. Here
it is not the case and the merge just makes the history unnecessarily
confusing.

 Also, if you do create merges it's strongly recommended to merge your
branch into master and not the other way round. There is a whole article
about it with graphs and everything which seems to explain it well at
https://developer.atlassian.com/blog/2016/04/stop-foxtrots-now/ (just
ignore Atlassian advertisement toward the end), so I won't repeat it.

 Finally, if you do want to make a "topic branch" merge into master but
hadn't created a branch for your changes since the beginning (if you did,
there would be no problem as you'd just do "git checkout master" and "git
merge my-branch" when you're ready to merge it), you can always correct the
situation: suppose you have local commits A,B,C on master which are
logically-related and so you think it would, finally, make sense to put
them on a branch "my-alphabetic-fixes" and merge them as a single whole
instead of doing the rebase as explained above. In this case you could do
the following:

        % git branch my-alphabetic-fixes # create new branch for your changes
        % git fetch # fetch the latest changes from the repository
        % git status # verify that you don't have any unsaved changes left
        % git reset --hard origin/master # THIS WILL LOSE ALL UNSAVED WORK!
        % git merge my-alphabetic-fixes # do the merge as usual
        % git push

 If you wanted to ensure that a merge commit is created, even if there had
been no changes on origin/master in the meanwhile, you can use "--no-ff"
option of "git merge".


 To finish on a somewhat philosophical note, initially I thought that it
was pretty important to have a nice linear history (as do all the people
coming from svn or cvs, of course, because dealing with branches in these
systems is such a pain). However the more I work with git, more I start to
appreciate having each change done in its own independent branch. My
current ideal workflow is to create a branch for any changes that require
more than one commit and then merge it using --no-ff, but some projects go
even further and create branches for absolutely *all* changes, see e.g. git
itself (https://github.com/git/git/commits/cd1c2e7301). I don't think we're
going to do this in lmi (yet?), but this clearly does have many advantages.

 Please let me know if you have any questions,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]