anchor.diff:        ENDIF.
       ENDIF.
   
  -    rv_html = rv_html && '<u>Objects</u><table border="1">' && gc_newline.
  +    rv_html = rv_html && '<table border="1">' && gc_newline &&
  +      '<tr>'                                  && gc_newline &&
  +      '<td><u>Local object</u></td>'          && gc_newline &&
  +      '<td></td>'                             && gc_newline &&
  +      '<td><u>Remote file</u></td>'           && gc_newline &&
  +      '<td></td>'                             && gc_newline &&
  +      '</tr>'                                 && gc_newline.
  +
       LOOP AT lt_results ASSIGNING <ls_result>.
  -      IF <ls_result>-match = abap_false.
  +      lv_index = sy-tabix.
  +
  +      CLEAR lv_link.
  +      IF lv_status = 'match' AND <ls_result>-filename IS INITIAL.
  +        lv_link = '<a href="sapevent:add?' &&
  +          struct_encode( ig_structure1 = is_repo_persi ig_structure2 = <ls_result> )
  +          && '">add</a>'.
  +      ELSEIF <ls_result>-match = abap_false.
           lv_link = '<a href="sapevent:diff?' &&
             struct_encode( ig_structure1 = <ls_result> ig_structure2 = ls_repo ) &&
             '">diff</a>'.
  +      ENDIF.
  +
  +      IF lv_span = 0.
  +        READ TABLE lt_results INTO ls_next INDEX lv_index.
  +        WHILE ls_next-obj_type = <ls_result>-obj_type
  +            AND ls_next-obj_name = <ls_result>-obj_name.
  +          lv_span  = lv_span + 1.
  +          lv_index = lv_index + 1.
  +          READ TABLE lt_results INTO ls_next INDEX lv_index.
  +          IF sy-subrc <> 0.
  +            EXIT. " current loop.
  +          ENDIF.
  +        ENDWHILE.
  +
  +        lv_object = '<td rowspan="' &&
  +          lv_span &&
  +          '" valign="top">' &&
  +          <ls_result>-obj_type &&
  +          '&nbsp;' &&
  +          <ls_result>-obj_name  &&
  +          '</td>' && gc_newline.
         ELSE.
  -        CLEAR lv_link.
  +        CLEAR lv_object.
         ENDIF.
   
         rv_html = rv_html &&
           '<tr>'                                    && gc_newline &&
  -        '<td>' && <ls_result>-obj_type && '</td>' && gc_newline &&
  -        '<td>' && <ls_result>-obj_name && '</td>' && gc_newline &&
  +        lv_object                                 &&
           '<td>' && <ls_result>-match && '</td>'    && gc_newline &&
           '<td>' && <ls_result>-filename && '</td>' && gc_newline &&
           '<td>' && lv_link && '</td>'              && gc_newline &&
           '</tr>'                                   && gc_newline.
  +
  +      lv_span = lv_span - 1.
       ENDLOOP.
       rv_html = rv_html && '</table>' && gc_newline.
   
       CASE lv_status.
  -      WHEN 'match'.
  -        rv_html = rv_html && '<a href="sapevent:add?'
  -                  && struct_encode( is_repo_persi ) && '">add</a>'.
         WHEN 'commit'.
           rv_html = rv_html && '<a href="sapevent:commit?'
                     && struct_encode( ls_repo ) && '">commit</a>'.
         WHEN 'pull'.
           rv_html = rv_html && '<a href="sapevent:pull?'
                     && struct_encode( is_repo_persi ) && '">pull</a>'.
  -      WHEN OTHERS.
  -        _raise 'status unknown'.
       ENDCASE.
   
       rv_html = rv_html && '<br><br><br>'.
  
positive.code: 
    METHOD add.
  
      DEFINE _add.
        append initial line to lt_spopli assigning <ls_spopli>.
        <ls_spopli>-varoption = &1.                           "#EC NOTEXT
      END-OF-DEFINITION.
  
      DATA: lt_files   TYPE tt_files,
            ls_item    TYPE st_item,
            ls_comment TYPE st_comment,
            lv_branch  TYPE t_sha1,
            ls_repo    TYPE st_repo,
            lt_spopli  TYPE TABLE OF spopli,
            lv_answer  TYPE c.
  
      FIELD-SYMBOLS: <ls_spopli> LIKE LINE OF lt_spopli.
  
  
      _add 'PROG Program'.
      _add 'DTEL Data Element'.
      _add 'DOMA Domain'.
      _add 'CLAS Class'.
      _add 'INTF Interface'.
      _add 'TABL Table/Structure'.
      _add 'TTYP Table Type'.
      _add 'VIEW View'.
      _add 'SHLP Search Help'.
      _add 'ENQU Lock Object'.
      _add 'SSFO Smart Form'.
      _add 'MSAG Message Class'.
      _add 'TRAN Transaction'.
      _add 'FUGR Function Group (todo)'.
      _add 'FORM SAP Script (todo)'.
  *table contents
  *lock object
  *web dynpro
  
      CALL FUNCTION 'POPUP_TO_DECIDE_LIST'
        EXPORTING
          start_col          = 10
          start_row          = 5
          textline1          = 'Choose object type'
          titel              = 'Choose object type'
        IMPORTING
          answer             = lv_answer
        TABLES
          t_spopli           = lt_spopli
        EXCEPTIONS
          not_enough_answers = 1
          too_much_answers   = 2
          too_much_marks     = 3
          OTHERS             = 4.                             "#EC NOTEXT
      IF sy-subrc <> 0.
        _raise 'error from decide_list'.
      ENDIF.
      IF lv_answer = 'A'. " Cancelled
        RETURN.
      ENDIF.
  
      READ TABLE lt_spopli ASSIGNING <ls_spopli> WITH KEY selflag = abap_true.
      ASSERT sy-subrc = 0.
      ls_item-obj_type = <ls_spopli>-varoption.
  
      ls_item-obj_name = get_object( ls_item-obj_type ).
      IF ls_item-obj_name IS INITIAL.
        RETURN.
      ENDIF.
  
      SELECT SINGLE obj_name FROM tadir
        INTO ls_item-obj_name
        WHERE pgmid = 'R3TR'
        AND object = ls_item-obj_type
        AND obj_name = ls_item-obj_name
        AND devclass = is_repo_persi-package.
      IF sy-subrc <> 0.
        _raise 'Object not found or in wrong package'.
      ENDIF.
  
      lt_files = lcl_serialize=>serialize( ls_item ).
  
      ls_comment = popup_comment( ).
      IF ls_comment IS INITIAL.
  
negative.code:                  document = 'https://github.com/larshp/abapGit' ).
            WHEN 'add'.
              struct_decode( EXPORTING iv_string = getdata
                             CHANGING cg_structure = ls_result ).
              struct_decode( EXPORTING iv_string = getdata
                             CHANGING cg_structure = ls_repo_persi ).
              CLEAR ls_item.
              MOVE-CORRESPONDING ls_result TO ls_item.
              add( is_item       = ls_item
                   is_repo_persi = ls_repo_persi ).
            WHEN 'uninstall'.
              struct_decode( EXPORTING iv_string = getdata
                             CHANGING cg_structure = ls_repo_persi ).
  