Вопрос

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.

Это было полезно?

Решение

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.

Другие советы

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.

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

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.

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.

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.

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.

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).

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.

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.

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).

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.

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.

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.

Лицензировано под: CC-BY-SA с атрибуция
scroll top