Bogdan
Bogdan

Reputation: 8246

git workflow with rebasing

I've worked so far with SVN, GIT and Mercurial, for the latter two the workflow always consisted just of pull / merge / push. Now I'm working on a project where the workflow involves rebasing often from parent branch and I'm not sure I understand entirely what is happening or if my workflow is the right one. I'm doing all of my work in a designated branch, so:

git checkout dvl_bkend      // This is 'parent' branch
git checkout -b dvl_bogdan  // Created my own branch 

Now all of below from my own branch. As I start a coding session:

git pull --rebase -s recursive -X ours origin dvl_bkend

Do coding and stuff, as soon as I have something stable-ish

git add stuff
git commit stuff
// rinse and repeat above two steps

Now when I have something ready for push.

git pull --rebase -s recursive -X ours origin dvl_bkend

At this point I would want to push to my dvl_bogdan but I can't saying that I need to pull first. So I:

git pull origin dvl_bogdan

Now this gives me conflicts that I need to merge (no ideea why this is happening?) and at this point I'm guessing something is not right. Anyway if I resolve conflicts I can then:

git push origin dvl_bogdan

Repeat all steps above until I'm ready for a pull request. Then repeat them some more. Where am I messing up with my flow? I've somehow managed to get in a situation where rebasing kept applying duplicate commits:

   bogdan   5b31717  Merge branch 'develop_bogdan' of xx into develop_bogdan     8 May 2013

   Bogdan Neacsa    810d753  Updated payment service to recieve an Account entity now rather that creating it itself. Also change…   8 May 2013

   bogdan   429f97b  Fix to model and service in payments. Quick fix to tests after changes.     8 May 2013

   Bogdan Neacsa    7c6ff32  Updated payment service to recieve an Account entity now rather that creating it itself. Also change…   8 May 2013

   bogdan   d74ce5a  Fix to model and service in payments. Quick fix to tests after changes.     8 May 2013

   Bogdan Neacsa    8ab401e  Updated payment service to recieve an Account entity now rather that creating it itself. Also change…   8 May 2013

   bogdan   259349b  Fix to model and service in payments. Quick fix to tests after changes.     8 May 2013

Thanks, Bogdan

EDIT: ------------ part unclear to me -------------------

So I'm on my dvl_bogdan branch, and it's synced with me remote branch, that is if I do:

git pull origin dvl_bogdan

This states I'm up to date. Now I do:

git pull --rebase -s recursive -X ours origin dvl_bkend

And this does not give me any conflicts. But now when I try:

git push origin dvl_bogdan

It asks me to do a pull before I can push and this pull will give me conflicts. I can't really understand what is going one here.

Upvotes: 0

Views: 354

Answers (2)

michas
michas

Reputation: 26555

Expicitly on the unclear part:

git pull origin dvl_bogdan

This will do a git fetch, which updates origin/dvl_bogdan and a git merge, which tries to apply all changes from origin/dvl_bogdan to your local dvl_bogdan. If it tells you, you are up to date. Then no one else pushed on that branch. (As expected as it seems you intend to work on this branch alone.)

git pull --rebase -s recursive -X ours origin dvl_bkend

This will do again a git fetch to update origin/dvl_bkend. Then a rebase will copy all your changes and apply them to origin/dvl_bkend. The resulting branch is completely unrelated to your dvl_bogdan. Use gitk origin/dvl_bogdan...dvl_bogdan now to see your situation: You have a common base, on which there is one branch(1) with your original commits ending on origin/dvl_bogdan and another branch(2) with contains changes from dvl_bkend with the copies of your changes on top.

git push origin dvl_bogdan

Now you try to push the branch(2) to branch(1), which does not work as this is no fast forward push.

To solve this, face the fact that origin/dvl_bkend and origin/dvl_bogdan are two different, already published branches. You need to merge both with a merge commit, use git fetch && git merge origin/dvl_bkend or simply git pull, which is doing exactly the same.

Alternatively it is possible to do a force push to update dvl_bogdan anyway, but be really sure you know what you are doing in this case.

Upvotes: 1

michas
michas

Reputation: 26555

The general idea sounds perfectly fine. A few comments:

  • A local branches is able to track its corresponding remote upstream branch. Setting an upstream branch is always a good idea, as it is the default for many operations like push and pull. Use git branch -vv to see which local branches you have and which remote branch they track.

  • Rebasing is changing history. Never change history you already published. This will lead to duplicate commit entries otherwise. A correctly set upstream helps you with that.

  • Set git config push.default to a good value. (see git help config) I would recommend "current" or "simple" if you have a recent git version.

  • Be sure you understand the meaning of "-s recursive -X ours". It might ignore upstream changes needed for the project.

  • Consider setting merge.ff=false. This will make sure whenever you do a merge a corresponding merge commit is created. But remember now to always pull with the --rebase option, otherwise each pull will create a merge commit, too. - A good alias is convenient.

I would recommend the following slightly adapted workflow:

  • first set up you config:

    git config --global push.default current
    git config --global merge.ff false
    git config --global alias.up 'pull --rebase'
    
  • create your local branch

    git checkout dvl_bkend
    git branch -vv # dvl_bkend should track something like "origin/dvl_bkend"
    git branch -m dvl_bogdan # creating your own branch by renaming the other is an easy way of tracking the original upstream
    
  • Work on the code. Commit frequently whenever you have finished some task. You can only roll back to states you committed. Once in a while do git up to integrate upstream changes and notice conflicting changes.

  • Once you are finished with your work and think about making it available to others:

    git rebase -i # have a look on your commits. You can reorder them, squash them together, correct errors in commit messages, etc.
    
    git log -p -w --reverse  @{u}.. # a final look at all the changes you are about to push
    
    git push --set-upstream # push your changes to your own remote branch and change the upstream to track your own branch from now on.
    
  • once you have pushed you final commits, you want to merge the branch back:

    git merge origin/dvl_bkend # optional, to notice potential merge conflicts
    git checkout dvl_bkend
    git merge --no-ff origin/dvl_bogdan
    git push
    

Upvotes: 1

Related Questions