{"thread":{"id":"38667","subject":"Easy Non-Fast-Forward Pushes","startedAt":"2015-02-27T16:20:19Z","lastAt":"2015-03-05T01:42:53Z","messageCount":5,"participants":["Lasse Kliemann","Stefan Beller","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"256746","messageId":"loom.20150227T170215-199@post.gmane.org","threadId":"38667","inReplyTo":null,"subject":"Easy Non-Fast-Forward Pushes","fromName":"Lasse Kliemann","fromEmail":"lasse@lassekliemann.de","sentAt":"2015-02-27T16:20:19Z","receivedAt":"2015-02-27T16:20:19Z","isPatch":false,"sender":{"key":"lasse@lassekliemann.de","avatar":null},"body":"As far as I understand, a push will always modify (or add) a ref in the\nremote repository. When pushing to branch B, then the ref pointing to the\nlast commit in this branch will be moved, provided that this can be done in\na fast-forward way. Otherwise the push will fail.\n\nThe following options exist:\n\n(1) force the push\n(2) fetch, merge, then push\n(3) push to a different branch\n\nI don't want (1), for obvious reasons.\n\nOption (2) implies that a particular person has to do the merge, namely the\nperson for whom the push is failing, or in other words: the person\nunfortunate enough not being the first to push. (This reminds me of\nSubversion: whoever tries to commit after someone else has committed will\nhave the burden of an update and possible merge.)\n\nOption (3) allows others to recognize the situation, and anyone with\nrepository access can do a merge. This is a good thing. However, I am\nconfused as to what branch name should be used for this. In Mercurial, we\nwould say that a new \"head\" is created, and anyone can recognize this by\nusing \"hg heads\" and do a merge if he feels competent enough. (A \"head\" in\nMercurial is a revision without children.) Can something similar be done in\nGit? I'd like to provide my co-workers with a command which they can always\nuse to push their changes to a central repository in order that I can see\nwhat has happened and do merges accordingly. In Mercurial, such a command\nwould simply be \"hg commit && hg push -f\". Then I can use \"hg heads\" to see\nif any new heads have grown, and if so, do merges. Upon their next pull,\nthese merges would manifest themselves in the repositories of my co-workers,\nand everything will be fine for them. So, im looking for the equivalent of\nthat workflow in Git. Thanks a lot!\n"},{"id":"256749","messageId":"CAGZ79kZ3_ohE6ebY5MvOk6+QfChppR_OtcmVaw5LBoutTWm3ZA@mail.gmail.com","threadId":"38667","inReplyTo":"loom.20150227T170215-199@post.gmane.org","subject":"Re: Easy Non-Fast-Forward Pushes","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2015-02-27T17:40:46Z","receivedAt":"2015-02-27T17:40:46Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Fri, Feb 27, 2015 at 8:20 AM, Lasse Kliemann <lasse@lassekliemann.de> wrote:\n> As far as I understand, a push will always modify (or add) a ref in the\n> remote repository. When pushing to branch B, then the ref pointing to the\n> last commit in this branch will be moved, provided that this can be done in\n> a fast-forward way. Otherwise the push will fail.\n>\n> The following options exist:\n>\n> (1) force the push\n> (2) fetch, merge, then push\n> (3) push to a different branch\n>\n> I don't want (1), for obvious reasons.\n>\n> Option (2) implies that a particular person has to do the merge, namely the\n> person for whom the push is failing, or in other words: the person\n> unfortunate enough not being the first to push. (This reminds me of\n> Subversion: whoever tries to commit after someone else has committed will\n> have the burden of an update and possible merge.)\n>\n> Option (3) allows others to recognize the situation, and anyone with\n> repository access can do a merge. This is a good thing. However, I am\n> confused as to what branch name should be used for this. In Mercurial, we\n> would say that a new \"head\" is created, and anyone can recognize this by\n> using \"hg heads\" and do a merge if he feels competent enough. (A \"head\" in\n> Mercurial is a revision without children.) Can something similar be done in\n> Git? I'd like to provide my co-workers with a command which they can always\n> use to push their changes to a central repository in order that I can see\n> what has happened and do merges accordingly. In Mercurial, such a command\n> would simply be \"hg commit && hg push -f\".\n\nFor a high level workflow with pure git, everything must be a branch\nor a tag IMHO,\n(I cannot really think of other ways).\n\nSo maybe you create a bash alias for\nalias gitup='git push origin HEAD:${USER}/$(date -Iseconds)'\nwhich would push your current tip of the repository to the remote with\nquite a unique name.\n\nThen you could also do a \"git commit -a && gitup\" to push your changes\nto the server\nAs the integrator you could then integrate branches with\n    \"git fetch origin && git merge origin/sbeller/2015-02-27T09:34:47-0800\"\n\nSo it is doable. Though I am not convinced of the workflow.\nMaybe you want to look at Gerrit or GitLab  (both are open\nsource web userinterfaces, where you can push changes to\nand approve them)\n\n\n>Then I can use \"hg heads\" to see\n> if any new heads have grown, and if so, do merges. Upon their next pull,\n> these merges would manifest themselves in the repositories of my co-workers,\n> and everything will be fine for them. So, im looking for the equivalent of\n> that workflow in Git. Thanks a lot!\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"256751","messageId":"xmqq8ufjjhos.fsf@gitster.dls.corp.google.com","threadId":"38667","inReplyTo":"loom.20150227T170215-199@post.gmane.org","subject":"Re: Easy Non-Fast-Forward Pushes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-02-27T19:08:35Z","receivedAt":"2015-02-27T19:08:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lasse Kliemann <lasse@lassekliemann.de> writes:\n\n> As far as I understand, a push will always modify (or add) a ref in the\n> remote repository. When pushing to branch B, then the ref pointing to the\n> last commit in this branch will be moved, provided that this can be done in\n> a fast-forward way. Otherwise the push will fail.\n>\n> The following options exist:\n>\n> (1) force the push\n> (2) fetch, merge, then push\n> (3) push to a different branch\n>\n> I don't want (1), for obvious reasons.\n>\n> Option (2) implies that a particular person has to do the merge, namely the\n> person for whom the push is failing, or in other words: the person\n> unfortunate enough not being the first to push. (This reminds me of\n> Subversion: whoever tries to commit after someone else has committed will\n> have the burden of an update and possible merge.)\n>\n> Option (3) allows others to recognize the situation, and anyone with\n> repository access can do a merge. This is a good thing. However, I am\n> confused as to what branch name should be used for this. In Mercurial, we\n> would say that a new \"head\" is created, and anyone can recognize this by\n> using \"hg heads\" and do a merge if he feels competent enough. (A \"head\" in\n> Mercurial is a revision without children.) Can something similar be done in\n> Git? I'd like to provide my co-workers with a command which they can always\n> use to push their changes to a central repository in order that I can see\n> what has happened and do merges accordingly. In Mercurial, such a command\n> would simply be \"hg commit && hg push -f\". Then I can use \"hg heads\" to see\n> if any new heads have grown, and if so, do merges. Upon their next pull,\n> these merges would manifest themselves in the repositories of my co-workers,\n> and everything will be fine for them. So, im looking for the equivalent of\n> that workflow in Git. Thanks a lot!\n\nI do not think I agree with the premise of the above in the first\nplace.\n\nThe person whose push is failing is not a \"victim\".  Everybody who\npushes is working together with others to advance what is hosted in\nthe repository he or she is pushing into.\n\nIf your work you failed to push is independent from others, then\n\"fetch-merge-push\" will be conflict-less and that is no basis to\ncomplain that you had to do extra work to get your change to the\ncommons.\n\nIf your work does conflict, what does it mean?  It means that other\npeople did some work in the same area as you just have worked on.\nWho are the best equipped to resolve such a conflict?\n\nTrue, you are not the only one who can understand the conflict.\nThose whose work in the same area that caused the conflict may know\nthe nature of their own changes just as well as you know your\nchanges, so they are equally qualified as you are.  But you are\namong the people a lot better qualified to understand and resolve\nthis conflict correctly than a random joe who was not involved in\nchanges that happened during the time your work was done offline\nwhile the shared commons were advancing.\n\nUnlike your view to see conflict resolution is a \"burden\", implying\n\"after I push my changes out, it is other people's problem to\ncorrectly integrate their changes, and it will not be my problem if\nthey break the change I did before they did with the merges\", the\nworkflow Git suggests when it rejects a non-fast-forward push\nencourages more effective collaboration by making sure that the\nopportunity to integrate _your_ own changes correctly to the shared\ncommon is given to _you_.\n\nHaving said all that.\n\nThere may be cases where you are far less qualified to resolve the\nconflict than other people who were involed in it.  After\n\n    $ git push\n    ... results in no-ff\n    $ git pull \n    ... results in conflict\n\nthe changes that overlap with your work can be found in this:\n\n    $ git log ..MERGE_HEAD\n\nAnd those who worked on them may know the area you and they both\nworked on a lot better than you.  And I fully understand and agree\nwith you that you and they need a way to communicate and makes it\neasy for you to ask them for help.\n\nI however do not think an anonymous \"split head\" (i.e. 'master' that\nis split 47 ways because different people punted on their conflict\nresolution and left their work based on older state not usable by\nthe collective commons) is the best way to do so.  Your option (3)\nencourages a workflow where it is OK to punt after saying \"I gave\nrandom others to resolve if/when they feel like it\", while making\nit more difficult for you to communicate those others that are more\nqualified to help you---you have to say which one of 47 split heads\nyou want them to take a look to help you.\n\nYour message to ask somebody for help would say what your changes\nwere for, what changes from them conflicted with that, and because\nyou do not understand some of their changes you do not know how best\nto adjust your changes on top of theirs (yes, adjusting your changes\nto the updated shared commons is what a merge resolution is about).\nAs a part of that communication, pushing your work, that is based on\nan older shared common from their point of view, to a branch whose\nname is taken after the topic you were working on, i.e. what your\nchanges were for, would help (or a non-branch ref, such as\nrefs/helpme/lasse-<topic>) a lot better than \"Hey, here is a random\nunexplained half-done work based on an older version of 'master'.\nFeel free to grab it and integrate.  I don't bother understanding\nand resolving the conflicts with more recent state of the project\",\nwhich is how Option (3) seems to be aiming at.\n"},{"id":"256807","messageId":"ygeioel2cw1.fsf@lassekliemann.de","threadId":"38667","inReplyTo":"CAGZ79kZ3_ohE6ebY5MvOk6+QfChppR_OtcmVaw5LBoutTWm3ZA@mail.gmail.com","subject":"Re: Easy Non-Fast-Forward Pushes","fromName":"Lasse Kliemann","fromEmail":"lasse@lassekliemann.de","sentAt":"2015-03-01T11:08:46Z","receivedAt":"2015-03-01T11:08:46Z","isPatch":false,"sender":{"key":"lasse@lassekliemann.de","avatar":null},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> So maybe you create a bash alias for\n> alias gitup='git push origin HEAD:${USER}/$(date -Iseconds)'\n> which would push your current tip of the repository to the remote with\n> quite a unique name.\n>\n> Then you could also do a \"git commit -a && gitup\" to push your changes\n> to the server\n> As the integrator you could then integrate branches with\n>     \"git fetch origin && git merge origin/sbeller/2015-02-27T09:34:47-0800\"\n>\n> So it is doable. Though I am not convinced of the workflow.\n\nThis solution is not too bad, I thought, but there should be a way to\nremove those branches once I have integrated them. Otherwise the\nrepository might get cluttered, and I found that those branches are\nparticularly annoying when viewing a graphical representation of the\ncommit graph.\n\nDeleting is possible, using 'git push origin :BRANCH'. But then, anyone\nwith pushing capabilities could do this! I don't like the possibility of\none team member messing up another's commit, be it on purpose or\naccidentally.\n\nIn Gitlab, branches can be protected. For this to work, however, I would\nneed fixed names. So I would assign one branch to each team member, make\nthose branches (let's call them \"personal branches\" for now) protected,\nand then configure their systems (by shell aliases, scripts, ...) to the\nfollowing:\n\n1. Try pushing to origin/master. If it works, fine. If not, goto 2.\n\n2. Push to the appropriate personal branch.\n\nThis system does not prevent someone pushing to another's personal\nbranch, thereby possibly making a fast-forward push impossible. So step\nnumber 2 may fail due to this, but this might be an acceptable risk.\n\nThanks a lot for your thoughts.\n"},{"id":"257049","messageId":"xmqqfv9k5iea.fsf@gitster.dls.corp.google.com","threadId":"38667","inReplyTo":"ygeioel2cw1.fsf@lassekliemann.de","subject":"Re: Easy Non-Fast-Forward Pushes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-03-05T01:42:53Z","receivedAt":"2015-03-05T01:42:53Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lasse Kliemann <lasse@lassekliemann.de> writes:\n\n> 1. Try pushing to origin/master. If it works, fine. If not, goto 2.\n>\n> 2. Push to the appropriate personal branch.\n\nI wonder what happens to this user _after_ that change gets\nintegrated on the project side.  Presumably somebody picks up the\nchange from the \"personal branch\", does necessary merge and updates\nthe master, so the next time \"git pull\" is done, it will\nfast-forward?\n\nI have a feeling that running trivial merges on the server-side when\na push is made, and immedately pulling that result back might help\nsuch userbase who does not care too much about the history better,\ninstead of using the bare-metal 'git pull' and 'git push'.  You'd be\nscripting on the client side to do the above two steps for your end\nusers anyway, so it would not be too much of a stretch to make that\nscript a bit smarter still?\n"}]}