2

I am working on a local copy of a large project on github. Most of the changes I make are modifications to tailor the application for a speific use case, as such they are not going to be accepted by the maintainer. I am trying to figure out the best way I can regularly update my local branch with changes made in the master branch, but without overwriting changes I have made. For example I could use:

git checkout my_branch git merge master

Then push mybranch to a seperate project master on github

If this the recommended way to have your own copy of a git project with regular updates from a master project?

5

There is no easy way to get updates from upstream while maintaining local changes to the code base. At some point, there will likely be conflicts, and you will need to resolve them manually.

Rebasing your changes onto the current state of upstream is not a viable solution in the long term, especially if your changes are more than a handful of commits. Since your adaptions are never merged back into the upstream repository, each time you rebase you will have to rebase everything you've ever done. That means resolving the same conflicts again and again. Rebasing also “rewrites” history which means that merging your branch becomes absolutely impossible.

If you need to keep your current workflow, it might be better to stop your main branch from tracking any upstream branch, and handle all merges manually – so effectively the commands you are suggesting. A git pull upstream master is almost the same as git fetch upstream; git merge upstream/master. Doing the merge manually will give you more control. Merging instead of rebasing also reduces your work load in the long run.

However, Git is not a suitable tool to manage different modifications of a code base. The term “version control” is slightly misleading here. This is not because Git is a bad tool, but because this is an inherently difficult problem. This problem becomes a lot easier if the original code base is sufficiently configurable so that you don't have to edit the code in order to implement your changes – in OOP speak, it should obey the open/closed principle.

While your problem-specific adaptions do not have any value for the original project, making it more configurable certainly would. The best strategy in the long term is therefore to make small changes to the original code to make it more configurable. This could mean setting some options in a configuration file, adding a plugin system, hooks and callbacks for certain events, or introducing dependency injection. Once those changes are in the upstream project, you can implement your changes without having to touch the upstream code, which significantly reduces your maintenance burden. Your problem-specific plugins would live in a completely separate project.

If the upstream project does not accept your modifications, maintaining a small set of patches as a compatibility layer is still better than making all your changes directly in the upstream code base.

1

You could

  • Stash your changes in your local working directory, do a git pull, then apply your stashes. This will keep your changes upto date, but your branches will diverge as soon as you make a commit. I recommend this only if you need to make an update between commits.

    git stash && git pull origin master && git stash apply. 
    
  • Do a git pull --rebase instead of a regular merge-based pull. A rebase will find the first common ancestor between the remote master branch and your local commits, apply the remote commits, then apply your local commits on top of them.

You may run into frequent conflicts, of course, in your specific use case (since you say the original maintainer of the remote branch has no interest in it and may happily overwrite your changes), but it is a very useful pattern and has the added benefit of keeping your commit history strictly linear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.