233

I am the new developer - this is my first programming position.

My issue is this: We use git - I cut a branch from our develop branch, then I start working on the minor task I've been assigned. It's very slow, because I'm inexperienced. By the time I'm ready to merge my branch back into develop the others have made so many changes that resolving the conflicts is overwhelming (it actually seems easier to scrap my work and start over on the task, which of course is not a sustainable solution).

How do I overcome this? Is there a tactic I can use other than 'be better at coding'? I intend to bring this up with my supervisor next week.

Christophe
  • 74,672
  • 10
  • 115
  • 187
K--
  • 2,529
  • 3
  • 10
  • 12
  • 170
    you dont need to only merge your branch into develop only when you are finished. you can merge develop into your feature branch incrementally whenever you like, to make the final merge smaller. – DavidB Aug 17 '18 at 12:42
  • 17
    Be sure you're doing the merging process right. Only your files should be affected and only your changes should be applied to the dev branch. If you're getting random conflicts, chances are you done the merge wrong or others are messing up the revision order. It's a good chance to educate yourself and possibly others in merging right. Some folks have a hard time understanding it's changes, not files that are being merged. So revisions ordering out of sync would cause conflicts on files you never touched. –  Aug 17 '18 at 13:00
  • 17
    Also be sure your editor is set right. Sometimes editors "fixes" tabs and spaces so when you edit a file, and attempt to commit back, it changes the entire file. You should make sure before committing that only your changes are being committed to the branch and fix your editor. –  Aug 17 '18 at 13:05
  • 32
    There is one odd thing here "I start working on the minor task " and tons of merge conflicts normally do not match. I just merged a 2 week major update branch into an experimental development and we had 10 (!) conflicts that were not auto-resolvable. You do not get tons of conflicts unless your task is "change variable names over all files". Not for MINOR tasks. – TomTom Aug 17 '18 at 16:07
  • 1
    You have to talk to your manager. He has to control the tasking so conflicts don't happen as much. Unless your tasks are taking you weeks to complete, there is almost no reason to conflicts. – ventsyv Aug 17 '18 at 16:20
  • 53
    Obligatory xkcd: https://xkcd.com/1597/ – E.D. Aug 17 '18 at 21:27
  • 2
    "...unless your task is 'change variable names over all files'", sounds about right, I never have found a version control setup that was good at handling variable renaming, which is a bit unfortunate. – jrh Aug 17 '18 at 22:30
  • 2
    If you merge the main development branch back into your own feature branch at a date long after you made your branch, I would totally expect a silly number of conflicts. But merging your work into the development branch, I'm not sure why you would have conflicts unless others on the team have also been working on the exact same files as you – chiliNUT Aug 18 '18 at 08:17
  • 4
    @chiliNUT I thought merging is at its core a symmetrical operation (changes on two branches are applied to one base), even though it is asymmetrically worded. Why do you suggest that the number of conflicts is dependent of the "direction" of the merge? Because of the order in which the changes are applied? That's possible if several changes on *develop* conflict with the same single change in *mybranch*; but [rerere](https://git-scm.com/book/en/v2/Git-Tools-Rerere) should take care of these multiple pseudo conflicts, shouldn't it? – Peter - Reinstate Monica Aug 19 '18 at 03:07
  • 1
    @PeterA.Schneider your right, I mispoke. I would expect there to be more modified files, not necessarily conflicts – chiliNUT Aug 19 '18 at 03:40
  • 3
    the problem is developer is not reintegrating regularly. it's not about "being ready to merge" it's about "checking to see what is ready to be merged" and determining if you should merge it now, or later (gonna happen either way, and you will learn sooner is typically better.) separately, you can always manually diff your changes into a second clone of the repo using a diff tool. if you're inexperienced this may help you until you become more familiar with the tools and processes required to be an effective developer on a fast-paced/large team (the presence of git is irrelevant.) – Shaun Wilson Aug 19 '18 at 06:36
  • 1
    On an opensource project this might happen (although a bit of coordination should first happen in chat/mailing lists). In a company which pays someone with the title of 'program manager' this is absolutely unacceptable if it becomes routine. A sign of tragic incapacity from the manager who can't avoid developers to stomp on each others' feet. – user3834459 Aug 20 '18 at 07:31
  • 1
    Have you tried talking to your team members? Do they have the same issue? Do they have it with the same frequency? How do they deal with it? – Jasper N. Brouwer Aug 20 '18 at 14:58
  • Perhaps ask about using branches per feature, then there's no competition within the branch, and each feature is merged or as a pull request in turn onto the develop branch once ready. – Vix Aug 20 '18 at 21:10
  • 3
    @TomTom _"we had 10 (!) conflicts that were not auto-resolvable"_ So, how long did it take to manually resolve 10-factorial conflicts? :) – code_dredd Aug 20 '18 at 21:15
  • 2
    @daisy It might help to think of git as tracking lines of code, not files. If you edit a line and somebody else edits a line then there is a conflict. In that case you just have to decide what that line should be doing and whose version is most correct or rewrite/remove that line entirely. If you never edited the line then something else may have happened and you can usually take "their" side of the merge conflict and move on. – Marie Aug 21 '18 at 12:45
  • your choices basically are to `git merge --no-ff develop` into your feature branch, or `git rebase -i develop` into your feature branch. Maybe see if your colleagues have a recommendation. – billrichards Aug 22 '18 at 01:16
  • Let me second @DavidB here - maybe you don't know that the proper way to merge is to merge the main branch into yours first, so all the changes are incorporated fairly easily, and only then merge your offshoot into the main trunk. As a new developer, I'd hope your manager is giving some fairly circumscribed problems to deal with, so you're not having to change something all over the place. Or if that's the case, maybe you're maintaining horribly written software, which is a larger problem we can't really help you with here :-). – George M Reinstate Monica Aug 22 '18 at 22:40
  • David has good advice with often merging the other way. But it is not sure it is always good to merge develop branch into yours. It depends on the purpose of your additions. – mathreadler Aug 23 '18 at 08:57
  • Count your blessings that you *have* branches, and aren’t using something like SVN (which, yes, has branches too; but they’re essentially unusable). – Konrad Rudolph Aug 23 '18 at 09:46
  • 1
    Good software should have **no, zero conflicts**. You just need "more separate classes", it's that simple. No need for complex comp-sci terms even. – Fattie Aug 24 '18 at 09:09
  • LOL @KonradRudolph if this was on SVN, the problem wouldn't come up, because you have to know how to program properly. (Using software ideas from 50 years ago like "modularization".) – Fattie Aug 24 '18 at 09:11
  • 1
    There can be easily merge conflicts even as simple as adding "import" entries at the top of the file, where two different branches add two different "import" entries at the exact same line. – Michael Tsang Aug 05 '20 at 08:36

15 Answers15

290

I assume you're using git. If so, make use of git rebase -i (the -i means interactive). Make it a daily task (even more frequently, if necessary) to rebase your branch against the develop branch. This brings in the changes incrementally every day (at least) to keep your feature branch up-to-date. If there are conflicts during your daily rebase, you need to have a talk with your team about who's working on what.

If you run it daily, you probably won't need the interactive part. Just let it do its thing.

I'm a fairly experienced developer, and it still takes me quite a bit of time to get up to speed on a new project. In your case, it sounds like you have several people working on the same project simultaneously, so it's either a very large project, or a new project that's evolving quickly. In either case, don't be worried if it takes you several months to get into the flow. If I switch projects for 2 or 3 weeks and then switch back, it can take me a few hours (or even a day or two) to get fully "back into" a project that I wrote 100% on my own!

In short, don't worry about being slow right now. The way to get better is to just keep practicing. Don't be afraid to ask other developers about aspects of the projects you don't understand.

EDIT:

Or use merge. That's also an option. So, the above would be: "make use of git rebase -i (the -i means interactive) or git merge". As for which one to use, talk it over with the rest of your team. They may (or may not) have strong preferences either way. It's clear some folks do have strong preferences.

Jacob Robbins
  • 2,011
  • 1
  • 10
  • 6
  • 23
    I guess this is the correct answer, but, IMO, just another example of bad Git design and terminology. Just what are you "rebasing"? Shouldn't this be called "update" or "checkout" or "merge" or some such??? (An answer below argues for "fetch") What's the point of source code control if **every day** you are forced to update??? – user949300 Aug 17 '18 at 18:26
  • 99
    It isn't updating or checking out though. It's taking whatever is exclusively in your branch, and adding your changes as if you just now made them on the other branch. I.e. your changes are now "based on" the other branch. Furthermore, there does not exist any magical source control system that knows your code and can know how to merge changes when multiple people modify the same files. You update every day to keep the conflicts small and manageable, and the changes fresh in everyone's minds so they know how to handle them. – Vectorjohn Aug 17 '18 at 18:51
  • 56
    @user949300 rebasing is distinct from merging, is much more nuanced and requires a better understanding of Git than a simple merge workflow. That's why I never recommend a workflow involving rebasing to a Git novice, because it leads to the assumption that rebasing is the only/default way to update a branch and leads to lots of unnecessary pitfalls and pain. In this case, merging will solve the problem in the same way and *neither* will solve the problem of merge conflicts in two long-running parallel feature branches. – Ant P Aug 17 '18 at 20:44
  • 10
    @AntP You're probably right about merging being the better option here, especially for a new user. Sometimes I merge, sometimes I rebase...depends on the circumstances. – Jacob Robbins Aug 17 '18 at 21:09
  • 6
    @user949300 ??? Merging changes from the main line into your branch regularly is a standard part of the process for *all* concurrent revision control systems. You also seem to think there's some downside to "updating" regularly. In most cases, it involves executing a single command which succeeds instantaneously. When it doesn't, then you have a conflict that you're going to need to resolve sooner or later. It's better to do it sooner before you build a bunch of other code on top of code that you will need to change. – Derek Elkins left SE Aug 18 '18 at 00:06
  • @DerekElkins Please state the single git command that "succeeds instantaneously." Seriously, I've googled this and theres fetch, merge, this rebase thing I've never used, and more... I'd really love to know. – user949300 Aug 18 '18 at 00:49
  • 14
    @user949300 `git pull` which is just a combination of `git fetch` and `git merge` (or you can add `--rebase` to do a rebase instead of a merge). Assuming you're only about a day behind, then on a LAN this will likely complete in less than second, it might take a couple seconds over the internet. Even over the internet and with minor merge conflicts, you can typically be up-to-date and merged cleanly in less than a minute. Spending five minutes spread throughout the week is a lot better than spending an hour at the end of week dealing with a gnarly merge conflict. – Derek Elkins left SE Aug 18 '18 at 01:15
  • 8
    @AntP It isn't that hard. All you need to know is not to rebase changes that have been pushed anywhere, and all the other caveats go away. Merging everywhere leads to a revision history that looks more like Guitar Hero than a record of previous states of the code base. And those little single commit merges when you pull just make you look incompetent. That's why I actually don't recommend using `pull` for a newbie. Learn to `fetch` and then make your own decision about `merge` or `rebase` on a case by case basis first. – jpmc26 Aug 18 '18 at 01:18
  • 5
    @AntP Rebasing is AFAIK always better as it leads to a cleaner history There's no risk if you only use a single branch (`develop` in the OP's case), i.e., rebase your local branch on the only branch you push to. Sometimes, resolving rebase conflicts may get harder than resolving merge conflicts, and then I fallback to merge. – maaartinus Aug 18 '18 at 03:35
  • 71
    No upvote from me because this answer is entirely fixated on rebasing. Rebasing can be a useful tool, but it should never be used mindlessly. For the day to day updating it's better to merge. Why? Because **every rebase is a lie**. You are telling history in a way it never happened. This can totally screw mighty tools like `git bisect`: The rebased stuff may not even compile, so `git bisect` is worthless on the resulting broken commits. @maaartinus: I, for one, prefer true history over linear history. If you rebase, you absolutely must check every new commit for sanity to avoid harmful lies. – cmaster - reinstate monica Aug 18 '18 at 08:46
  • 13
    @cmaster +1 - if you're rebasing every merge then you're not really utilising Git as a DVCS and you'd be better off just using SVN instead. Rebase is nice if you're merging from the same upstream branch and you're one or two commits ahead/behind, but beyond that merge is almost always the better option and *should always be the default choice*. Rebase obsession is like an epidemic among Git users. – Ant P Aug 18 '18 at 14:04
  • @AntP In your recent comment, you give no arguments at all. Using SVN is a pure non-sense, or did it catch up? Rebasing and merging is not mutually exclusive - you may be one of those working on feature1 and rebasing in order to keep the history simpler and then feature1 may get merged into master. – maaartinus Aug 18 '18 at 14:37
  • @maaartinus SVN is not as abysmal anymore as it used to be. But it still does not provide for a non-linear workflow easily: Creating a branch is a public action, and merging is still not the true 3-way merge that `git` uses. So, while you can theoretically create the same histories as with `git`, you can't in practice as you cannot create any fully private throw-away branches to record it. Also, merging is still not as robust as with `git`. Thus, history will be painfully linear as its restricted to the few public branches that you are willing to create. – cmaster - reinstate monica Aug 18 '18 at 16:54
  • 5
    The part of this answer that helps address the problem is to to be merging/rebasing *frequently*. Rebasing rather than merging will hit all of the same conflicts that merging will, and will not make them any easier to resolve. It just changes how the history looks afterwards. – Ben Aug 19 '18 at 14:04
  • 4
    @jpmc26 Rebasing is harder and more dangerous than you make out. If you make a mess of a merge, then the full history is still there, and you can go back and try again. If you make a mess of a rebase, your history is gone (unless you can figure out what the old HEAD commit id was). If I need to rebase code, I always create a new branch, so the old branch is still there if I mess up. I've shot myself in the foot enough times with rebase to be wary. – James_pic Aug 20 '18 at 11:46
  • 12
    @cmaster I'm sorry, I wish that you would post that as an answer so that I could disagree with you formally. Rebasing isn't a lie until it's public. I ***constantly*** rebase my working branches until I need to need to make them public. Having a humongous working set of commits and merges everywhere leads to difficult to follow commit history. It's also symptomatic of not relegating specific feature updates to specific branches but instead trying to make a super commit. – zero298 Aug 20 '18 at 14:19
  • 1
    @zero298 I've been in the situation myself of constantly rebasing my commits before making them public (because I had an SVN upstream :( ). And I tell you, everytime I did rebase a knew that I was creating a lie. If you are not aware that you are lying while doing it, you'll be hard put to tell a consistent story. I, for one, rechecked every single commit that was created by my rebasing, and that rechecking did stop me from publishing some utter nonsense. When I'm merging, I know that I've created every commit with a good tree, and that won't be changed by the merge. – cmaster - reinstate monica Aug 20 '18 at 15:18
  • 1
    @zero298 Archeology is best done with `git bisect` anyway... – cmaster - reinstate monica Aug 20 '18 at 15:18
  • 5
    @James_pic Nonsense. Create a temporary branch when you start (to mark the current `HEAD`) or learn how to use `reflog`. Or if you're well and truly terrified and paranoid, zip up the repository's directory before you start. (This is actually something I did in my early days of git, but it wasn't very long before I realized it was massive overkill.) It's always possible to recover from a borked rebase and isn't even hard. – jpmc26 Aug 20 '18 at 15:24
  • 2
    @jpmc26 That's exactly what James_pic was saying: "I always create a new branch, so the old branch is still there if I mess up". Whatever you do, you should always have the original commit IDs recorded *somewhere* before you start rebasing. This may be a branch, or a tag, or the reflog, or even pen and paper. If you don't know how to back up, rebasing can be disastrous. – cmaster - reinstate monica Aug 20 '18 at 20:23
  • @cmaster `reflog` keeps track of it automatically. It'll be there even if you do nothing specific. Even easy to find via Google: https://stackoverflow.com/q/134882/1394393 – jpmc26 Aug 20 '18 at 20:26
  • 5
    @cmaster rebasing is what makes bisect sensible. With rebase, you have a linear history of commits without branches, so you can take full advantage of bisect. If you have diverging and merging branches, finding the problematic commit is much more work. The goal of rebasing workflow is (IMO) to have this linear history of changes. – hyde Aug 20 '18 at 21:03
  • @jpmc26 I know. Nevertheless, I find it easier to just point a named branch at the right place. (I'm a C programmer; I know how to work with pointers ;-) ) Works well with my usual `git log` incantation, which will show the commit graph, allowing me to see how the (un-)rebased branches differ. Of course, if you prefer using the reflog, well `git` supports many different workflows :-) – cmaster - reinstate monica Aug 20 '18 at 21:30
  • @cmaster Yes, the extra branch is more convenient. I do it myself. But the point is that recovery is still both possible and not hard if you're a newb who just does the rebase and screws up everything before checking. So it's not dangerous in the sense of you're going to throw away a week of work by doing a basic rebase when someone else pushes changes. – jpmc26 Aug 20 '18 at 21:38
  • @jpmc26 I must confess, I wasn't aware of `reflog`. That would have been handy to know about on a couple of occasions in the past! But is it really good advice to newbies to use rebase religiously? Rebase can be a footgun, and I've been using git for a few years, but only today learned that it even has a safety mechanism. Maybe it's just because my first exposure to DVCSs was Mercurial, but rebase always feels like an antipattern. – James_pic Aug 21 '18 at 09:40
  • @James_pic Of course not religiously. Like anything, it depends on what you're doing. E.g., a hotfix commit needs to have your previous release as a parent even if you have newer changes, so you *have* to merge that into dev. But a clean history is desirable, and keeping merges to a minimum helps with that. It's no different to me than keeping your wiki or ticket system or any other documentation clean. I also think it's a better way of dealing with conflicts. It makes you adjust your changes in the commit where they happen rather than slap on a not easily identifiable fix at the end. – jpmc26 Aug 21 '18 at 15:34
  • @James_pic I find [OneFlow](http://endoflineblog.com/oneflow-a-git-branching-model-and-workflow)'s rebase style to be quite good, if you are looking for a little more guidance about when to rebase and when to merge. My practical advise is to neither rebase nor merge by default, but to configure git with `merge=ffonly` so that git just errors out if it can't fast-forward merge when you pull. Then you can look at the nature of the mismatch and make a decision about how to integrate, with a preference for rebase. – jpmc26 Aug 21 '18 at 15:38
  • What is the advantage of `rebase -i` over just `rebase` for this usecase of just rebasing a branch onto another one (i.e. when there are no commit messages/contents to manipulate)? – Paŭlo Ebermann Aug 21 '18 at 17:51
  • @PaŭloEbermann For this use case, I would leave off the `-i`. Don't know why I defaulted to that option in my answer. If we're just trying to get our own feature branch up-to-date, it isn't necessary. If you want to squash commits, etc., then it's needed. – Jacob Robbins Aug 21 '18 at 18:52
  • 1
    This answer covers the key points (notwithstanding philosophical arguments about rebasing, and whether this answer should perhaps cover alternative approaches), and goes out of its way to note that the real core of the issue -- too many people working on non-isolated areas of code -- is a social one and may require a social solution. So it's a +1 from me – Lightness Races in Orbit Aug 22 '18 at 10:42
  • Agree with @AntP and others. There's no need to suggest a rebase here. A daily merge with the `develop` branch is simpler and just as effective. Though neither thing really solves the core problem, which appears to be that the OP's company is not dividing work up effectively and has multiple developers changing the same files at the same time. Merging/rebasing daily changes the giant headache at the end into a series of smaller headaches, but it doesn't remove the pain entirely. – aroth Aug 22 '18 at 13:05
  • @aroth it won't even divide up the headaches if the conflicts are on long-running parallel feature branches since there will be nothing to merge until one of those branches is merged back upstream. The solution here is either to move to much more transient feature branches (or no feature branches at all) or to be much more careful about what work is done in parallel. Or both. – Ant P Aug 22 '18 at 13:55
  • Is it a good idea to tell a new developer to use rebase? I thought that tool was a tad dangerous to use. – Clockwork Aug 25 '18 at 21:30
  • @user949300 "rebase" is not a bad/inaccurate/misleading term for what it is/does. You are repositioning the point at which your branch diverged from master, or whatever was your starting point. You could call this starting point the base of your branch, hence "rebase". My first experience with rebasing was just short of horrific because I more than once ended up with conflicts I couldn't properly resolve, and lost track of the baseline against which some of the conflicting changes were made (because I did numerous commits on my branch before rebasing), but... – Zenilogix Aug 27 '18 at 00:56
  • @user949300 (cont'd) ...If you rebase frequently, your cumulative work remains coherent with the state of the "main" branch you will ultimately merge back into. One practice I found worked well was to rebase up to the point of the final merge so that the merge becomes a linear change on top of the latest "main". – Zenilogix Aug 27 '18 at 01:01
  • @JacobRobbins to make this answer better, you might consider updating your answer above with the suggestion to use either merge or rebase with a warning about rebase. Rebase is certainly a risker tool for the less sophisticated as your comment above suggested and merging is another, most often easier, option. – zquintana Aug 28 '18 at 16:48
  • Please do not suggest rebase for new developers, that might confuse them a lot, but a merge is a good option for novice. – Duke Aug 02 '21 at 13:53
130

This might be a sign of bad software engineering on the company's part. Too many inter dependencies, different issues with overlapping features, attempting to tackle issues in the wrong order etc. can cause the situation you are describing. I suggest regularly merging develop into your branch during development

Ivan Anatolievich
  • 1,327
  • 1
  • 6
  • 3
  • 10
    This is coding 101 stuff as you mentioned. Not necessarily an accurate reflection on the new employee. –  Aug 17 '18 at 13:26
  • 2
    @Ivan Anatolievich OP says that they're branched off of develop, not master, FYI – Matthew FitzGerald-Chamberlain Aug 17 '18 at 14:50
  • 7
    This answer shows exactly why I don't like GIT: it's again another tool for teams to avoid having a proper management and decent planning. The answer to everything is "who cares, you can always use that command later", instead of avoiding problems before they happen. – motoDrizzt Aug 20 '18 at 10:29
  • I thought too this could be a modularisation issue. – SaltySub2 Aug 21 '18 at 03:17
  • 8
    my first thought was also a sign of bad practices, devs shouldn't be working on the same files for the most part. If a small project is having this many conflicts, everyone else must just be resolving conflicts all day long without doing any work! – Aequitas Aug 21 '18 at 05:44
  • 14
    @motoDrizzt What? I have never heard anyone make that argument. – jpmc26 Aug 21 '18 at 15:56
  • 1
    Of course, conflicts happen, and then `git` (or `mercurial`, or whatever) is a tool to resolve them. But if you are distributing work among team members properly, conflicts should not happen too often. To cite http://www.paulgraham.com/head.html: "Don't have multiple people editing the same piece of code. [...] of course you can't safely redesign something other people are working on. It's not just that you'd have to ask permission. You don't even let yourself think of such things.". – Giorgio Aug 21 '18 at 19:13
  • Exactly. Good software should have **no** conflicts. You just need "more separate classes", it's that simple. No need for complex comp-sci terms even. – Fattie Aug 24 '18 at 09:09
  • This was my very first thought. There is something wrong with the structure of the code or the way branches are being made in relation to the features. Merge conflicts happen (not ideally, but in reality) and sometimes they are bad but that should not be the norm. – Stoopkid Aug 24 '18 at 17:36
98

The accepted answers I think are more of a technical "how to use Git better" nature, I think this is more of a team problem than an engineering or tooling problem.

If you're encountering a lot of merge conflicts it means that you and someone else on the team are stepping on each others toes.
You or they should aim to develop personal space while coding and avoid working in areas that are busy already.

In my team, we tend towards a high degree of task-ownership.
I'll usually take full and complete ownership of two or three files at a time and work on them in a branch for a day or two at most.
Typically if anyone else touches those files it's only if absolutely necessary for their own tasks, we generally don't work together on the same block of tasks at all!

If you're finding that you have to merge a lot at all then either all your teams code is in one place (which is something to avoid in itself) or all your tasks are.

All that said, as a new dev you're probably not in a position to enforce, request or even really suggest any sort of restructuring.
What I'd expect is that your tasks have been assigned as "learn-the-ropes" stuff that should be reasonably approachable at your skill level in order to ease you into the team. They've probably been culled from the tasks of a co-worker who is still working in the same area, hence your merge conflicts.
The solution to this then is to plug away at it, solve the problems, deal with the merge conflicts as best you can and don't worry too much, as long as you're doing your best it's down to your manager to worry about your progress.
You'll get faster and more confident as you go, and your co-workers will give you more autonomy and get in your way less as a consequence.

Rowan
  • 1,079
  • 6
  • 6
  • 4
    I think you hit the nail on the head with the co-worker conflict. Merge conflicts are a regular thing, but they are generally limited to a handful of files. – Matthieu M. Aug 17 '18 at 15:23
  • Yesterday I dealt with just three minor merge conflicts. just a function I'd put in place with an input variable, and then the other guy had removed the need for that variable. That's the kind of problems we encounter as a well-delineated team. If you have to replace a whole line or weigh up which block of code is "correct" then something has gone pretty wrong. God forbid you have hundreds of tiny problems throughout the file. That's usually more of an auto-formatting problem. Setting up Visual Studio to handle it consistently solves that completely. –  Aug 17 '18 at 15:32
  • 10
    This sounds like a corollary to [Conway's Law](https://en.wikipedia.org/wiki/Conway%27s_law), and the [Single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle) -- i.e. that if people are working on different problems then ideally they'll be editing separate parts of the source code. – ChrisW Aug 17 '18 at 17:04
  • @ChrisW Ideally. OP doesn't say whether the project is a tangled mess. (And being new, may not know the difference.) – StackOverthrow Aug 17 '18 at 22:42
  • 7
    While I agree that a poor process or poor design can lead to a large amount of conflicts, I'm pretty confident that the issue is simply that the OP isn't merging in the mainline regularly. I don't agree that "taking full and complete ownership" of files is appropriate as a matter of course. I don't want my team having a constant overhead of keeping track of who "owns" what now, asking "permission" to make changes, or guessing what files they should "claim". Only rarely, when significantly rewriting a component, have I asked team members to inform me if they were going to change certain files. – Derek Elkins left SE Aug 18 '18 at 00:40
  • As the new guy on the team, don't try to change the team. There are companies where you can pull that off, but in most companies you can't. And shouldn't. – Mast Aug 19 '18 at 11:12
  • 1
    ChrisW has the right idea with what I was driving at. Generally speaking Ownership in my company takes the form of application functionality, I take complete ownership of the Search Filter system as a task and as it happens, nobody else needs to touch the related files under most circumstances. My feeling is that it's very likely OP as a new starter has been given minor parts of tasks closely related to an ongoing set of tasks by another dev. Meaning the other dev is working in the same part of the codebase and they're getting in each other's way. – Rowan Aug 19 '18 at 12:04
  • This is the right answer. The vast majority of the time, merge conflicts are a symptom of poor project management. They mean that with multiple people are working on the same part of the codebase at the same time, which is a bad idea even when it doesn't create merge conflicts. – Mason Wheeler Aug 20 '18 at 12:43
  • @Rowan Files or functionality approach when splitting up tasks? Both? Curious, cheers. – SaltySub2 Aug 21 '18 at 03:18
  • @SaltySub Functionality first, generally speaking each task on our Scrum-board is in a distinct section of the project, Whoever is most familiar with a section works on it, usually the person who previously worked on it unless there's something really esoteric that needs doing. So a given set of files is frequently 95%+ written by one person with only minor tweaks by other members of the team. Example: I wrote the bulk of the code for our product-details page but struggled with the image-carousel, so another member of the team who's more familiar with Bootstrap took it over. I usually do UI/UX – Rowan Aug 21 '18 at 08:42
  • 1
    @Rowan Cool yeah I thought as much. Functionality separation can also help with file separation (sets of functions in different files etc) and this IMO helps with merging. – SaltySub2 Aug 22 '18 at 09:43
  • Definitely. Object-oriented development and Modularity are key to efficient code and development. They allow problems to be local and code to be split amongst a team without conflict. Every problem becomes a box containing a solution if it's done right. – Rowan Aug 22 '18 at 10:25
  • Upvote and agree. I ask interview question(s) around "Do you understand what Single Responsibility is?" and "Yes, I think it is so important". But the written-code is mini-god-classes that do everything......and becomes the intersection of so many merge conflicts. (actually) adhering to single-responsibility (.cs, .java. .whatever classes/files)..you get less merge conflicts. – granadaCoder Oct 20 '22 at 17:46
29

The most important thing about merging is that the longer you wait, the more painful it gets. And the problem grows more than linear. Three times as many conflicts are nine times as much work. There are some strategies:

Merge with the development branch whenever it changes, so you are always close to it, and never have a huge number of conflicts.

If you take a long time, then it may be because you spend most of the time figuring out what the changes are, and then a small amount of time implementing the changes. If that is the case, merge with the development branch before you start actual code changes.

Talk to your colleagues about strategies to avoid conflicts. You get conflicts if two people edit the same code. Not just the same file, but the same code. So I need a new function functionA and you need a new function functionB, and we both add it at the end of the same file, we have a conflict. If we add it in different places, no conflict. If we both add it at a place in the file where it logically belongs, chances are we have no conflict.

If you have conflicts, get a good diff tool, so you can compare the develop branch before your merge, your code before the merge, your original code, and the merged code, and merge by hand.

Worst case: You don't throw your work away, but use a good diff tool to find out exactly what changes you made, branch again from develop, and apply all the changes you made manually instead of retyping them.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
15

By the time I'm ready to merge my branch back into develop (emphasis mine)

Handling conflicts in git merge is often simpler than in git rebase. In Git merge you can see the whole list of files that have been modified at once. No matter how many commits have been done by other coworkers, you will have to merge once. With rebase workflow, you may end up getting the same conflicts over and over and have to review them manually. You can end up fixing the 13th commit and feel like you can't see light out of the tunnel.

By my experience, when I attempted to naively resolve repeated rebase conflicts I ended up losing someone's modifications or with an application that did not even compile. Often I and coworkers did a lot of work but became so overwhelmed by the complexity of repeating conflicts that we had to abort and lose our previous work after a handful of rebase commits.

I am going to suggest you a few techniques but they can only help the merge get easier than automate the task.

  • Resource/language files. If you have additive changes to a resource file, make sure you always move them to the end of file so that you can easily recall your changes against others' changes. You may be able to copy&paste your changes on the bottom, or just remove the conflict markers
  • Do. Not. ABSOLUTELY. RE-format. Neither you nor your fellow developers shall perform a "massive code reformat" during daily work. Code reformat adds an excessive number of false positives in conflict management. Code reformat can be done
    • Incrementally, e.g. by every developer on every commit, as soon as they use an automated tool (e.g. Eclipse has an option to reformat on save, vanilla Visual Studio has none). Absolutely every developer must use the same code formatting standards, coded into a format file that is eaten by your IDE. To give you an idea, if it's 4 spaces or 2 tabs it doesn't matter, but it really matters if everyone use the same.
    • Just before release, by a team leader. If a "code reformat" commit occurs when people are not working on branches, i.e. before they branch, things will make easier
  • Review the work splitting between coworkers. This one is the part where most engineering comes. As pointed by other answers, it is design smell if multiple developers doing different tasks have to touch the same resources. You may have to discuss with your team leader about what part is to be modified by each concurrent developer.

I also have seen some bad habits in Git workflows in my teams. Often people overcommit to their branches. I personally witnessed a developer adding 10 to 20 commits labeled "fix", each committing one or two lines. Our policy is that commits are labeled with JIRA tickets to give you an idea.

@JacobRobbins suggests to make git rebase a daily task. I would like to push his approach forward.

First, use rebase once just to reduce the number of commits to a handful. And rebase only onto the original develop branch, which is the commit you have branched from. When I say handful, I could mean 3 or 4 (e.g. all front end, all back end, all database patches) or any humanly-reasonable figure. After you have consolidated them, use fetch and work your rebase over the upstream branch. This won't save you from conflict unless your team reviews their own approach, but will make your life less painful.

If you have additional questions on the specific tasks, feel free to search and ask on Stackoverflow.

[Edit] about the no-reformat and boy scout rule. I have slightly reworded RE-format to highlight that what I am meaning is the task of formatting from scratch the entire source file, including code that was not touched by you. In opposite to always format your own code, which is perfectly boy-scouty, a number of developers, including myself, are used to reformat the entire file with the IDE's capabilities. When the file is touched by others, even if the affected lines are not changed in their contents and semantics, Git will see it as a conflict. Only a very powerful language-aware editor may suggest that the conflict is only related to formatting and auto-merge the best-formatted fragment. But I don't have evidence of any such a tool.

After all, the boy scout rule does not mandate you to clean other people's mess. Just yours.

  • 3
    It is largely a matter of opinion, but I disagree that merge conflicts are easier to handle than rebase conflicts. When you rebase, you essentially apply commits one by one, keeping the scope of the merge conflicts much smaller and easier to follow (you apply YOUR changes that you know - not someone else's changes that you don't). You may have to solve more merge conflicts this way (due to touching the same files multiple times across commits), but they will be smaller and easier to tackle. – user622505 Aug 20 '18 at 03:39
  • 3
    Regarding reformatting, while VS can't do it automatically on save, if you set "When I paste" to "Indent and format" in "Tools" --> "Options" --> "Text Editor" --> "" --> "Formatting", that means it auto formats on paste. This allows the sequence of three keystrokes: ctrl-A, ctrl-C, ctrl-V to have the desired result. That said, +1 for **Do. Not. ABSOLUTELY. Reformat.** Except as you outline under very carefully controlled conditions. – dgnuff Aug 20 '18 at 18:32
  • 1
    Bob Martin readers should note that the [Boy Scout Rule](https://deviq.com/boy-scout-rule/) must be applied with restraint if you are working in a team (if you are working on your own, you have much more flexibility). If you interpret the rule as "It is my duty as a coder to fix literally everything in every file that isn't perfect the instant I find out about it, nevermind what anyone else is working on.", you will end up with a gigantic amount of hard to resolve conflicts, and it will be a giant mess no matter how good your intentions are. – jrh Aug 20 '18 at 19:35
  • (I just found [the old article](https://web.archive.org/web/20180203045156/http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule)), "Always check a module in cleaner than when you checked it out."; since what "module" means is rather unclear, I'd advise a strategy more like "Always improve the cleanliness of code that you are assigned to work on". that means that improving code that is used for a lot of stuff may have to wait until there is a coordinated team effort, but IMO that is better than constantly having conflicts to resolve. – jrh Aug 20 '18 at 19:49
  • 2
    You you feel a need to reformat or lightly refactor the code, do it before or after your meaningful commit. It will not only reduce conflicts, but also helps future reader of your commit, including reviewers – max630 Aug 21 '18 at 07:16
  • Since this question doesn't have a language specified, I'm not sure I agree with **Do. Not. ABSOLUTELY. Reformat.** In some languages, especially where whitespace is syntactically meaningful, reformatting is a lot less of a disaster and more common in day-to-day work. – Aaron M. Eshbach Aug 21 '18 at 12:45
  • 1
    From my C# culture, "re-formatting" means the action of formatting a whole code file or even entire repository **where formatting is only related to readability**. If your language uses whitespace meaningfully, you shouldn't mess with whitespaces in LOCs that are not your own. Conversely, your language of choice may still allow *non-meaningful* whitespaces (e.g. before a brace) that can be "reformatted" according to a readability standard – usr-local-ΕΨΗΕΛΩΝ Aug 21 '18 at 13:18
  • @max630 there is a caveat. If the reformat commit occurs at the end of your commit chain, you can easily discard that reformat commit and redo the format after rebase. Sometimes you feel the temptation of doing reformat in the middle of a long chain. When you rebase, you will see that the reformat commit is the most painful, so you choose to skip it. Unfortunately, the next commits will be all dependent on the previously done reformat, so **your own code** will start to raise plenties of conflicts. Whether *theirs* is the right choice depends on the specific repository, so use it wisely. – usr-local-ΕΨΗΕΛΩΝ Aug 22 '18 at 10:51
  • This answer is by far my favorite. But let me add @daisy that perhaps you're feeling overwhelmed because you're not using a good tool. Do you know about Sublime Text? It's immensely helpful in guiding you during merges, so you can clearly see what your own changes are and how they are affected by others. Check it out.. – George M Reinstate Monica Aug 22 '18 at 22:46
  • @usr-local-ΕΨΗΕΛΩΝ when you say "re-formatting" do you mean pure whitespace changes? – jrh Aug 25 '18 at 20:49
  • @jrh in general any tool (including changes to braces) that is used to improve code readability without affecting the algorithm. Advanced IDEs can ignore *pure whitespaces* in conflict resolution – usr-local-ΕΨΗΕΛΩΝ Aug 26 '18 at 18:29
  • The scope of a reformatter **includes** rearranging members, variables, namespace/package imports – usr-local-ΕΨΗΕΛΩΝ Aug 27 '18 at 10:48
10

You get merge conflicts if the changes you did in your branch are near the changes your colleagues did in the develop branch in the meantime, that is, if you and your colleagues changed the same lines of code or adjacent lines in the same file.

So to reduce the likelihood of merge conflicts, you can try to merge earlier so that your colleagues changed fewer lines in the meantime, or you can try to change fewer lines yourself.

To change fewer lines yourself, make sure to only make changes related to your task.

If you need to experiment with different ways to achieve your goal, maybe some of your experiments changed lines that don't really need to be changed? Undo these changes before merging.

There are also some Git commands that can help you change as few lines as possible:

  • git diff and git diff --staged to see which lines you changed.
  • git add -p to only add some of your changes in a file.
  • git commit --amend and git rebase -i to tweak commits you already made in your local feature branch before pushing them to other Git repositories.

(Changing as few lines as possible can also make it easier to review your work or to use tools that work on the differences between commits such as git cherry-pick, git rebase, git bisect, and git blame.)

But even if you reduce the likelihood of merge conflicts, you will still run into merge conflicts sometimes. So don't be afraid of them, but learn how to resolve the conflicts.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Toxaris
  • 261
  • 1
  • 6
  • 1
    Also before merging, a `git fetch` and `git diff origin/develop` will show you a preview of your merge (sort of). Gives you a chance to clean up your changes before you get a ton of pointless conflicts. – Max Aug 21 '18 at 13:12
6

First, don't think about discarding your changes. You will lose opportunities to learn the merge process.

Second, find a person who worked on the files causing conflict. You can see the history. Talk to the person and resolve conflicts in those files. Do the same for other conflicts.

If there are too many conflicts, your task may be a minor one, but repetitive. Try to find a pattern. This would help in resolving conflicts by the Git UI client tools. I use TortoiseGit. It helps in merge.

And for avoiding in the future,

  • It's a very good practice to merge the develop branch regularly to your feature branch.

  • If you have CI enabled, see if the CI tool provides a branch build. This should build on every check in you make in your feature branch, but after the merge develop branch.

PKV
  • 181
  • 1
  • 4
2

By the time I'm ready to merge my branch back into develop the others have made so many changes that resolving the conflicts is overwhelming

This sounds like an ideal scenario for pair programming!

More info about the benefits and basic approaches:
https://gds.blog.gov.uk/2018/02/06/how-to-pair-program-effectively-in-6-steps/

You will naturally speed up over time from working on your own, but it can be daunting until that time comes, and is a long haul sometimes too. Also, while people can learn quickly being in a stressful environment always pressured to catch up, others who don't learn well under constant pressure will be hindered.

Instead of working on a branch on your own and trying to keep up with other devs who are obviously much faster than you, you'd instead work directly (same PC) with another dev. This way you get instant advice and will probably pick up tips how to speed up etc.

You'd have figure out the best approach for the particular code in your project, as pair programming doesn't always makes sense for some projects - although it arguably always makes sense for learning even if you just sit and watch someone more experienced than you (as long as they're a good dev, experience doesn't necessarily mean they use good practices).

Sitting with a faster, more experienced dev has potential to help by:

  • Will likely reduce merge conflicts as working with someone more experienced will increase the completion time as opposed to your working alone
  • As they'll be teaching you it's likely they will be slower than they would be working alone, so there may still be some merge conflicts and so can work through them with someone seasoned and so perhaps pick up some tips on saving time etc
  • Help you see potential tricks and ways to be speedier (although being slow is sometimes just simply a lack of experience rather than a lack of good practices)
  • Can ask questions immediately when something doesn't make sense or isn't 100% clear
  • Working 1:1 is valuable for learning because the person you would ask help from already understands the exact code and scenario as they're working on it, without pair programming you have to explain the code and scenario, which often ends up a problem and so you lose their time/attention on actually getting much needed advice
  • Get to know the thought process of someone more experienced and seasoned, and with good communications you'll most certainly learn new things

Is there a tactic I can use other than 'be better at coding'? I intend to bring this up with my supervisor next week.

My advice is to discuss pair programming with the other devs and then approach your supervisor. If they're decent they'll appreciate your initiative which has more chance for you to pitch the pros of pair programming (if they need that, most people know of it and it's common knowledge why it helps).

James
  • 243
  • 1
  • 16
  • Honestly who downvoted :( this isn't some wild guess, this happens in my workplace and is proven to work! Incidently, I worked hard on other answers on other questions on this site to be able to have 10 rep (above my associated rep) just to be able to suggest "pair programming" in this one because no-one suggested it. I worked really hard to answer this. – James Aug 24 '18 at 10:28
2

There are a few underlying problems here. Your problems merging are very likely not your fault and are more commonly a symptom of bad practices.

1) Ideally you would merge your branch into develop every day. Try to have working code at least once a day that passes all tests so you can merge into develop.

2) If you don't have working code at any point during your usual work day you probably have too big chunks of code to work on. You need to break your task up into smaller tasks that can be finished (ideally independently of each other) quicker so that you can merge.

3) Your projects files are likely too big. If there are many merge conflicts for a file there are too many people working on one file. Ideally something one person is working on should be separate from what everyone else is working on.

4) Your team might be too big. If you find it easier to throw away a whole feature and start over, it's likely there are too many people committing code to the same repository.

5) You might not have consistent code formatting standards. If you don't all consistently use the same code formatting you will get many different conflicts for the same code. Depending on how your git is set up these might even come down to whitespace conflicts (line endings, indentation, tabs vs spaces).

6) People might be pushing their changes directly to the develop branch.

Here's what you can do: 1) If you can not merge into develop every day, merge/rebase develop into your branch every day (or more often).
2) Try to have your code separated from every one else's code.
3) Talk to the rest of the team about smaller features, consistent coding standards and better code organization (smaller files, smaller functions).

xyious
  • 241
  • 1
  • 5
1

You should run regularly (daily) the command 'git fetch' (not git pull) from your development branch. This will get other peoples committed changes and bring them into your feature branch without attempting to integrate the changes into your branch.

This is something you should talk to the lead developer about (not necessarily your manager), because your company may have their own standards or recommended ways of handling this issue; it's very common. Don't wait until next week - find out the process now, and ask if you can commit some trivial work (such as code formatting or adding comments) so you can test the process.

  • 21
    I'm not sure this is correct. Git fetch will get remotes/origin/master up to date but you then need to merge remotes/origin/master into your feature branch (Or remotes/origin/develop if that's the flow they are using) – Richard Tingle Aug 17 '18 at 13:10
  • Assuming he's using git, it's also a good idea to learn how to squash your commit to meaningful parts. That way when you're ready to make a pull request, your commit is lean and straightforward and easy to understand. –  Aug 17 '18 at 13:10
  • @RichardTingle Correct, He's thinking of a rebase option. You simply fetch & rebase your branch with the dev branch. That will sync up everything. –  Aug 17 '18 at 13:12
  • 6
    @Dan I think that may be a matter of opinion. Personally I hate massive commits. Try git bisecting that! – Richard Tingle Aug 17 '18 at 13:12
  • 2
    @PeteCon "and bring them into your feature branch without attempting to integrate the changes into your branch". That seems like a contradictory statement. I think you mean bring them into your local repository without integrating them into your feature branch, but I'm not sure how that helps... – Jason Goemaat Aug 19 '18 at 01:03
1

Obviously first thing is to avoid having multiple people work on the same files in the first place, at least in a way which leads to difficult conflicts. Adding things into enumerations is no problem as long as a good code format is used. Changing control flow in different ways and moving code around is vastly more tricky. Sometimes this is inevitable nonetheless. You'll need to ask questions when resolving conflicts that are truly complex.

That said, I see many answers recommending to merge/rebase onto develop regularly. I would be much less enthusiastic about that sort of advice. Your goal at this point is to make the conflict solving process as easy and safe as possible. One thing which is going to help tremendously with that process is to have as many regression tests immediately available, including the new ones that are part of your new feature. If you synchronize your branch very regularly with develop, you will invariably end up having to resolve conflicts while you are half done actually implementing your feature. And that means that it will be much more difficult trying to figure out what the code is supposed to do, as you weren't done with it. Before attempting to merge, make sure that your branch is a coherent unit of change. Even better, rebase it into a single commit before merging.

I tried not to go into the merits of rebase over merge which is probably for another question. In this context the tools don't really matter.

Kafein
  • 416
  • 2
  • 4
1

It actually seems easier to scrap my work and start over on the task, which of course is not a sustainable solution)

Most of the time, this is what I do, the first time I fix a bug or make a change to the system, I am learning about how to do it. The next time I fix the same bug it only takes 1% of the time as I now understand the problem.

I also find that when I redo a bit of work, I write better code.....

Hence there is nothing wrong with creating a new branch from the master, redoing your work in it, while using your "private branch" to remind you what you need to do.

It is also possible that you have discovered a way to split your change into logical and correct parts, each that be merged into the master branch once completed. For example, the unit tests and changes to backend code can be done, and merged in. Then in a separate operation, you can do the UI changes that makes use of them, hence have less risk of someone else editing the same UI file.

Ian
  • 4,594
  • 18
  • 28
1

If you do not want to merge the develop branch into you branch too often, you can get a workflow which is more like svn by using git pull --rebase. This will pull the new commits and rebase your commits on them. This means when you merge your branch into develop, it will be a fast-forward merge (as if you would have added all your past commits at the same time one after another) and not have any merge conflicts, because you resolved them all during git pull --rebase.

But the more commits you make before merging either your branch into develop or develop into your branch, the more complicated will the next rebase get and it subverts the sense of feature-branches a bit, as your branch only exists as long as it is unmerged.

allo
  • 164
  • 7
1

When you work in common files, in either way you or your teammates need to resolve all conflicts before merging finishes hence at the first place please don't be upset. You are still doing project work and be proud of your work. Now to make a smarter move, you can follow some suggestions below.

  1. Divide tasks independently:

    Before you start your work, plan and divide whole tasks in such a way that assigned task for each team member is as much independent and modular as possible (to avoid potential conflicts while developing). You can approach to your scrum leader to assign some independent tasks for you as you are newbie.
  2. Merge granular frequent commits:

    Don't wait for full task to complete before final marge. Of Course any larger tasks can be partitioned into multiple subtasks. So better approach is to merge smaller commits for smaller subtasks at the same time frequently to avoid bulky conflict resolution.
  3. Rebase your branch frequently:

    Make a practice of frequent rebase to your local branch with remote one. You can use below command to frequently rebase your local branch with remote one,

    git pull --rebase #or
    git pull --rebase origin dev #when dev is remote branch
    

    That is so far the most useful git command for me in my development life.

  4. Work closely with teammates:

    If you really need to work parallelly with your teammate in common task, please work collaboratively. She can wait for sometime to avoid complex conflict resolution for your convenience as you are newbie and she is an expert.

  5. Be used to with git options:

    Use power of git merging tools. There are many convenient ways to resolve conflicts while merging. Merging strategies sometimes might help a lot. Be used to and fearless with git commands.

1

OP here - I'm a senior developer now. Some merge conflicts don't necessarily indicate poor software design; as @MichaelTsang points out, a conflict might arise from two branches each adding an import on the same line. You can make life easier by merging master into your feature branch regularly (not just before making a pull request). I've never found rebasing to be necessary. Thanks everyone!

K--
  • 2,529
  • 3
  • 10
  • 12