MergeBERT: Program Merge Conflict Resolution via Neural Transformers

1 INTRODUCTION . Collaborative software development relies on version control systems such as git to track changes across files . In most projects , developers work primarily in a branch of a software repository , periodically synchronizing their code changes with the main branch via pull requests ( Gousios et al. , 2016 ) . When multiple developers make concurrent changes to the same line of code , a merge conflict may occur . According to an empirical study of four large software projects by Zimmermann ( 2007 ) up to 46 % of all merge commits result in conflicts . Resolving merge conflicts is a time-consuming , complicated , and error-prone activity that requires understanding both the syntax and program semantics , often taking more time than developing a code feature itself ( Bird & Zimmermann , 2012 ) . Modern version control systems such as git utilize the diff3 algorithm for performing unstructured line-based three-way merge of input files ( Smith , 1998 ) . This algorithm aligns the two-way diffs of two versions of the code A and B over the common base O into a sequence of diff “ slots ” . At each slot , a change from eitherA or B is selected . If both program versions introduce a change at the same slot , a merge conflict is produced , and manual resolution of the conflicting modifications is required . A versatile , production-level merge conflict resolution system should be aware of programming language syntax and semantics yet be sufficiently flexible to work with any source code files , irrespective of the programming language . It should generalize to a wide variety of real-world merge conflicts beyond a specific merge type or a domain of software artifacts . Inspired by the exceptional performance of transformer models and self-supervised pretraining in natural language understanding and generation tasks ( Devlin et al. , 2019 ; Radford et al. , 2019 ; Liu et al. , 2019 ; Lewis et al. , 2019 ; Raffel et al. , 2020 ) as well as in the programming language domain ( Feng et al. , 2020 ; Svyatkovskiy et al. , 2020 ; Clement et al. , 2020 ; Tufano et al. , 2020 ; Ahmad et al. , 2021 ) , we introduce MergeBERT : a neural program merge framework based on token-level three-way differencing and transfer learning . We select a bidirectional transformer encoder ( BERT ) as our encoder implementation . As a bidirectional encoder , BERT allows to attend to code context surrounding the conflicting chunks , which is a key advantage over left-to-right language models . To endow our model with a basic knowledge of programming language syntax and semantics , we adopt a two-step training procedure : ( 1 ) unsupervised masked language model pretraining on a massively multilingual source code corpus , ( 2 ) supervised finetuning for the sequence classification task . We transfer weights of the pretrained encoder into a multi-input model architecture that encodes all inputs that a standard diff3 algorithm takes ( two two-way diffs of input programs ) as well as the edit sequence information , then aggregate them for learning . While MergeBERT utilizes BERT , other encoder architectures such as LSTM ( Hochreiter & Schmidhuber , 1997 ) , or efficient transformer variants like Poolingformer ( Zhang et al. , 2021 ) could also be utilized for this task . The paper contributions are as follows : ( 1 ) we introduce MergeBERT a novel transformer-based program merge framework that leverages token-level three-way differencing and formulates the task of generating the resolution sequence as a classification task over a set of primitive merge patterns extracted from real-world merge commit data , ( 2 ) we effectively transfer knowledge about program syntax and types of source code identifiers from millions of software programs to downstream sequence classification task of merge conflict resolution by using self-supervised pretraining ( see section 5 ) , which also makes this approach computationally more feasible , ( 3 ) we overcome several limitations of the existing neural program merge models Dinella et al . ( 2021 ) and semi-structured program merge tools like jsFSTMerge and JDime to improve upon the state-of-the-art by 2–3× ( see sections 7 and 8 ) , and finally , ( 4 ) we demonstrate that multilingual MergeBERT is sufficiently versatile to work with programs in Java , JavaScript , TypeScript , and C # , and can generalize to unseen languages without retraining . 1.1 RELATED WORK . There have been multiple attempts to improve merge algorithms by restricting the them to a particular programming language or a specific type of applications ( Mens , 2002 ) . Typically , such attempts result in algorithms that do not scale well or have a low coverage . Syntactic merge algorithms improve upon diff3 by verifying the syntactic correctness of the merged programs . Several syntactic program merge techniques have been proposed ( Westfechtel , 1991 ; Asklund , 1999 ) which are based on parse trees or abstract syntax trees and graphs . Apel et al . noted that structured and unstructured merge each has strengths and weaknesses . They developed a semi-structured merge tool , FSTMERGE , which switches between approaches ( Apel et al. , 2010 ) . They later introduced JDIME , an approach that automatically tunes a mixture of structured and unstructured merge based conflict locations ( Apel et al. , 2012 ) . AUTOMERGE tool ( Zhu & He , 2018 ) improves upon the JDIME by adding a built-in matcher to check output resolutions for the merges performed by JDIME . AUTOMERGE synthesizes resolutions only when the structured merge algorithm fails to complete a merge . Trindade Tavares et al . ( 2019 ) later implemented jsFSTMerge by adapting an off-the-shelf grammar for JavaScript and modifying the FSTMerge algorithm itself to address JavaScript specific issues . In addition , Pan et al . ( 2021 ) explore using program synthesis to learn repeated merge resolutions within a project . However , the approach is limited to a single C++ project , and only deals with restricted cases of import statements . Sousa et al . ( 2018 ) explore the use of program verification to certify that a merge obeys a semantic correctness criteria , but does not help resolve merge conflicts . 2 MOTIVATING EXAMPLE . In this section , we formulate the traditional line-level merge conflict resolution problem as a classification task and show how token-level formulation of diff3 helps to localize the merge conflicts . Fig . 1 provides an example merge conflict in JavaScript . Fig . 1 ( a ) on the left shows the standard diff3 markers “ < < < < < < < A.js ” , “ ||||||| O.js ” , “ ======= ” and “ > > > > > > > B.js ” , which denote the conflicting regions introduced by programs A , base O , and B respectively . Here , O represents the most common ancestor of programs A and B in the version control history . We denote the program text of diff3 conflicting regions as Aj , Bj , Oj , where j is a conflict index . The conflict index may be omitted when referring to programs consisting of a single conflict only . We refer to the program text outside the conflicting chunks , common to all merged programs versions , as a prefix and suffix , and denote it respectively as Pref and Suff throughout the paper . First , MergeBERT represents each line-level merge conflict instance at token level ( Fig . 1 ( b ) ) which localizes conflicting regions , yielding a ⊂ A , b ⊂ B , o ⊂ O , and then it invokes the neural model to predict a resolution via classification ( Fig . 1 ( c ) ) . Here , and throughout the paper we will use lower case notations to refer to attributes of token-level differencing ( e.g . a , b , and o are conflict regions produced by diff3 of token granularity ) . Intuitively , token diff3 first turns the line-structured text into a list of tokens ( including space and line delimiters ) , applies standard diff3 algorithm to the resulting documents , and reconstructs the merged document at line level . As a result of token-level merge , the whole “ let x = max ( y , ” string is cleanly merged , becoming a part of the program prefix , and “ ) ” is prepended to the program suffix . Token-level diff3 is a syntactic merge algorithm . As such , it does not guarantee semantic correctness of the merged program . In most cases ( 82 % ) , however , token merge matches the user resolution . Observe , that the resolution does not consist of any single line from eitherA orB since both edits modify a common line present in the base . Hence , earlier neural approaches such as DeepMerge ( Dinella et al. , 2021 ) would not be able to synthesize the resolution . On the other hand , structured merge techniques ( such as jsFSTMergeby Trindade Tavares et al . ( 2019 ) ) can not resolve the conflict as the conflict appears on a program statement , which leads to side effects ( e.g . syntactically incorrect code ) . A token-level merge can interleave edits within lines ( i.e. , tokens in which one edit does not conflict with another are trivially merged ) . Consider A ’ s edit of the var to let keyword . Such nonconflicting edits suffice to demonstrate the above . Likewise , consider the token-level conflict for the arguments to the max function : an appropriate model trained on JavaScript should be able to easily deduce that taking the edit from B ( i.e. , `` 11 , z '' ) captures the behavior of A ’ s edit as well . The suggested resolution gives an intuitive demonstration for how MergeBERT turns a complex line-level resolution into a simpler token-level classification problem . MergeBERT can deal with non-trivial real-world merges composed of multiple conflicting chunks . We include a complete example of such a merge conflict in the Appendix . 3 BACKGROUND : DATA-DRIVEN MERGE . Dinella et al . ( 2021 ) introduced the data-driven program merge problem as a supervised machine learning problem . A program merge consists of a 4-tuple of programs ( A , B , O , M ) , where 1 . The base program O is the most common ancestor in the version history for programs A and B , 2. diff3 produces an unstructured line-level conflict when applied to ( A , B , O ) , and 3 . M is the program with the developer resolution , having no conflicts . Given a set of such programs and merges ( A , B , O , M ) , the goal of a data-driven merge is to learn a function , merge , that maximizes the set of examples where merge ( A , B , O ) = M. Moreover , since a program may have multiple unstructured conflicts ( Aj , Bj , Oj , Mj ) , j=0 ... N , the data-driven merge considers the different merge tuples corresponding to the conflicting regions independently , and poses the learning problem over all the merge tuples present in ( A , B , O , M ) . Dinella et al . ( 2021 ) also provide an algorithm for extracting the exact resolution regions for each merge tuple and define a dataset that corresponds to non-trivial resolutions where the developer does not drop one of the changes in the resolution . Further , they provide a sequence-to-sequence encoder-decoder based architecture , where a bi-directional gated recurrent unit ( GRU ) is used for encoding the merge inputs comprising of ( A , B , O ) segments of a merge tuple , and a pointer mechanism is used to restrict the output to only choose from line segments present in the input . Given the restriction on copying only lines from inputs , the dataset defined in the paper did not consider merges where the resolution required token-level interleaving , such as the conflict in Figure 1 . And , lastly , the dataset consists of merge conflicts in a single language , JavaScript . In contrast , our paper addresses both of these limitations .

Summary: This paper addresses merge-conflict resolution in source code repositories. Whereas prior neural work (DeepMerge) can only do line-level resolutions (i.e., predict a resolution that chooses some sequence of entire lines from the original file version or the two divergent branches), this work refines the task further towards token level resolutions, thereby covering more interesting cases. Whereas DeepMerge cast the task as a pointer-sequence prediction (predicted a sequence of lines from the input), MergeBERT casts the task as a classification problem: for each conflict instance (some token-sequence conflict), one of 9 recipes are chosen to merge (e.g., just the original tokens, just one of the branches, some concatenation of the three, and some substitution of tokens in the original by concatenations). Similarly to DeepMerge, the input is encoded as a combination of aligned token sequences of the original snapshots and the divergent branches, as well as an encoding of the token-wise edit "script" for the pairwise diffs (same, inserted, deleted, replaced). But instead of encoding this edit sequence explicitly, MergeBERT uses it as a token type embedding in a Transformer encoder, along with a positional embedding and the token embedding itself.  The Transformer encoder is pre-trained with the masked language model objective, before fine-tuning on merge-conflict resolutions. The resulting tool is shown to resolve more merge conflicts than prior work, and also to generalize to a language unseen during pre-training or fine-tuning.