-1

I just realized that Git is ignoring whitespaces during merge by default. However, I would like that Git would consider whitespace during merge. Is there someone that knows how can I configure it?

I tried to install older versions, but I could not find. The steps to install older version on Ubuntu would be nice.

2 Answers2

4

Git should not ignore whitespace during merges, unless:

  • you add -Xignore-all-space (man page)
  • Or those changes were already merged in a previous merge commits
  • or you have defined a merge driver which would ignore whitespace (while a normal native git merge would not)

The OP GLEIPH GHIOTTO LIMA DE MENEZES confirms in the comments it is because of a merge driver which does not work well with the new merge default strategy ORT, resulting in a different context for diff.
Using merge -s recursive is enough for now to revert to the legacy behaviour.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • VonC, thanks for your answer. However, I just realized that Git is using a new strategy, named ort, and this was generating a different result that allows that the context of conflicting chunks also would change (it is described in the documentation https://git-scm.com/docs/git-merge). Thus, changed the strategy to recursive (-s recursive) and this resolved my problem. I replayed the merge 044a3c of SAIM (https://github.com/dice-group/SAIM) and I had two different answers. Unfortunately, there is no space to show the results in this answer. – GLEIPH GHIOTTO LIMA DE MENEZES Nov 13 '22 at 17:39
  • @GLEIPHGHIOTTOLIMADEMENEZES Good point. I have presented [ORT here](https://stackoverflow.com/a/64950077/6309). Since 2.36, the [merge backend has evolved](https://stackoverflow.com/a/71330184/6309). – VonC Nov 13 '22 at 19:46
  • thanks! I my case, the problem was the context changing. – GLEIPH GHIOTTO LIMA DE MENEZES Nov 14 '22 at 00:40
  • @GLEIPHGHIOTTOLIMADEMENEZES I have included your comment in the answer for more visibility. – VonC Nov 14 '22 at 07:06
  • thanks for your feedback. I may compare the results of both strategies in some projects and report them. – GLEIPH GHIOTTO LIMA DE MENEZES Nov 16 '22 at 12:47
0

I just realized that Git is using a new strategy, named ort, and this was generating a different result that allows the context of conflicting chunks also would change during the merge (it is described in the documentation https://git-scm.com/docs/git-merge). However I used this fact (context lines do not change) in my algorithm. Thus, I changed the strategy to recursive (-s recursive) and this resolved my problem.

I replayed the merge 044a3c of SAIM (https://github.com/dice-group/SAIM) and I had two different answers. Unfortunately, there is no space to show the results in this answer and I will show the first conflicting chunk reported for each strategy.

Ort strategy

        selfconfig.setEnabled(true);
    }

<<<<<<< HEAD
        private void performPropertyMapping() {
            Configuration config = Configuration.getInstance();
            config.getSource().properties.clear();
            config.getTarget().properties.clear();
            PropertyMapper propMapper = new PropertyMapper();
            String classSource = config.getSource().getClassOfendpoint();
            String classTarget = config.getTarget().getClassOfendpoint();
            if(classSource != null && classTarget != null) {
                showErrorMessage("Getting property mapping...");
                propMapping = propMapper.getPropertyMapping(config.getSource().endpoint,
                        config.getTarget().endpoint, classSource, classTarget);
                for(String s : propMapping.map.keySet())
                    for(Entry<String, Double> e : propMapping.map.get(s).entrySet()) {
                        System.out.println(s + " - " + e.getKey());
                        String s_abr=PrefixHelper.abbreviate(s);
                        sourceProps.add(s_abr);
                        config.getSource().properties.add(s_abr);
                        config.getSource().prefixes.put(PrefixHelper.getPrefixFromURI(s_abr), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s_abr)));
                        System.out.println("Adding source property: "+s_abr+"::::"+PrefixHelper.getPrefixFromURI(s_abr)+" -- "+PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s_abr)));
                        targetProps.add(PrefixHelper.abbreviate(e.getKey()));
                        String t_abr=PrefixHelper.abbreviate(e.getKey());
                        config.getTarget().properties.add(t_abr);
                        config.getTarget().prefixes.put(PrefixHelper.getPrefixFromURI(t_abr), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(t_abr)));
                        System.out.println("Adding target property: "+t_abr+"::::"+PrefixHelper.getPrefixFromURI(t_abr)+" -- "+PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(t_abr)));
=======

    /**
     * Little helper function to retrieve classes out of restrictions of the LIMES SPEC. Whereas, a
     * class is in a restriction of the format "?var rdf:type <class>".
     * @param ep
     * @return
     */
    private String getClassOfEndpoint(KBInfo ep) {
        for(String rest : ep.restrictions) {
            if(rest.matches(".* rdf:type .*"))
                return rest.substring(rest.indexOf("rdf:type")+8).replaceAll("<", "").replaceAll(">", "").trim();
        }
        return null;
    }

    private void showErrorMessage(String message) {
        layout.setComponentError(new UserError(message));
    }

    public boolean isValid() {
        manualMetricForm.validate();
        if(manualMetricForm.isValid()) {
            Configuration.getInstance().setMetricExpression(manualMetricForm.metricTextField.getValue().toString());
            Configuration.getInstance().setAcceptanceThreshold(Double.parseDouble(manualMetricForm.thresholdTextField.getValue().toString()));
            return true;
        } else {
            manualMetricForm.setComponentError(new UserError("Please insert something..."));
        }
        return false;
    }

    public class SelfConfigClickListener implements Button.ClickListener {
        Layout l;
        public SelfConfigClickListener(Layout l) {
            this.l=l;
        }
        @Override
        public void buttonClick(ClickEvent event) {
            // add all properties
            for(String s : sourceProps) {
                Configuration.getInstance().getSource().properties.add(s);
                Configuration.getInstance().getSource().prefixes.put(PrefixHelper.getPrefixFromURI(s), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s)));
                Configuration.getInstance().getSource().functions.put(s, "");
            }
            for(String s : targetProps) {
                Configuration.getInstance().getTarget().properties.add(s);
                Configuration.getInstance().getTarget().prefixes.put(PrefixHelper.getPrefixFromURI(s), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s)));
                Configuration.getInstance().getTarget().functions.put(s, "");
            }
            // run selfconfig
            l.removeAllComponents();
            Refresher refresher = new Refresher();
            SelfConfigRefreshListener listener = new SelfConfigRefreshListener();
            refresher.addListener(listener);
            addComponent(refresher);

            final ProgressIndicator indicator = new ProgressIndicator();
            indicator.setCaption("Progress");
            l.addComponent(indicator);
            indicator.setImmediate(true);

            final Panel stepPanel = new Panel("Starting self configuration");
            l.addComponent(stepPanel);

            new Thread() {
                public void run() {

                    float steps = 5f;
                    indicator.setValue(new Float(1f/steps));
                    indicator.requestRepaint();
                    stepPanel.setCaption("Getting source cache...");
                    HybridCache sourceCache = HybridCache.getData(Configuration.getInstance().getSource());
                    indicator.setValue(new Float(2f/steps));
                    indicator.requestRepaint();
                    stepPanel.setCaption("Getting target cache...");
                    HybridCache targetCache = HybridCache.getData(Configuration.getInstance().getTarget());
                    indicator.setValue(new Float(3f/steps));
                    stepPanel.setCaption("Performing self configuration...");
                    MeshBasedSelfConfigurator bsc = new MeshBasedSelfConfigurator(sourceCache, targetCache, 0.6, 0.5);
                    List<SimpleClassifier> cp = bsc.getBestInitialClassifiers();                        
                    indicator.setValue(new Float(4f/steps));
                    stepPanel.setCaption("Performed self configuration:");
                    for(SimpleClassifier cl : cp) {
                        System.out.println(cl);
>>>>>>> bbb3f6b
                    }

                }

Recursive strategy

        final int WIDTH = 800;
        final int NODESIZE = 100;

<<<<<<< HEAD
        private void performPropertyMapping() {
            Configuration config = Configuration.getInstance();
            config.getSource().properties.clear();
            config.getTarget().properties.clear();
            PropertyMapper propMapper = new PropertyMapper();
            String classSource = config.getSource().getClassOfendpoint();
            String classTarget = config.getTarget().getClassOfendpoint();
            if(classSource != null && classTarget != null) {
                showErrorMessage("Getting property mapping...");
                propMapping = propMapper.getPropertyMapping(config.getSource().endpoint,
                        config.getTarget().endpoint, classSource, classTarget);
                for(String s : propMapping.map.keySet())
                    for(Entry<String, Double> e : propMapping.map.get(s).entrySet()) {
                        System.out.println(s + " - " + e.getKey());
                        String s_abr=PrefixHelper.abbreviate(s);
                        sourceProps.add(s_abr);
                        config.getSource().properties.add(s_abr);
                        config.getSource().prefixes.put(PrefixHelper.getPrefixFromURI(s_abr), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s_abr)));
                        System.out.println("Adding source property: "+s_abr+"::::"+PrefixHelper.getPrefixFromURI(s_abr)+" -- "+PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(s_abr)));
                        targetProps.add(PrefixHelper.abbreviate(e.getKey()));
                        String t_abr=PrefixHelper.abbreviate(e.getKey());
                        config.getTarget().properties.add(t_abr);
                        config.getTarget().prefixes.put(PrefixHelper.getPrefixFromURI(t_abr), PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(t_abr)));
                        System.out.println("Adding target property: "+t_abr+"::::"+PrefixHelper.getPrefixFromURI(t_abr)+" -- "+PrefixHelper.getURI(PrefixHelper.getPrefixFromURI(t_abr)));
                    }
            } else {
                showErrorMessage("Cannot perform automatic property mapping due to missing class specifications.");
            }       
        }
=======
        Cytoscape.createNewSession();   
        String name = "MyName";
        CyNetwork cyNetwork = Cytoscape.createNetwork(name, false);     
        cyNetworkView = Cytoscape.createNetworkView(cyNetwork);

        cytographer = new Cytographer(cyNetwork, cyNetworkView, name, WIDTH, HEIGHT);
        cytographer.setImmediate(true);
        cytographer.setWidth(WIDTH + "px");
        cytographer.setHeight(HEIGHT + "px");
        cytographer.setTextVisible(true);       
        cytographer.setNodeSize(NODESIZE, true);    
>>>>>>> bbb3f6b
        
        return cytographer;     
    }
    

I'm not judging which is the better result, just the one that works for the algorithm I implemented.

Thanks!
Gleiph

  • Can you clarify please how getting a different merge conflict is helpful and resolves your question? Since both strategies result in a conflict requiring manual intervention it doesn’t seem like it does. – AD7six Nov 13 '22 at 18:15
  • @AD7six, both strategies result in conflicts. However, I perform a syntax analysis in the content of the chunks and I need to locate the line before and after the chunks in the parent versions. As the context changed (allowed by the ort strategy), the diff results that the line was deleted and I my algorithm returns a wrong answer. Thus, my problem was the context changing. Is it clear? I will try to adapt my algorithm in the near future, but we need to resolve it as soon as possible because of one deadline. – GLEIPH GHIOTTO LIMA DE MENEZES Nov 14 '22 at 00:46
  • `Is it clear?` not really, no :). The question is also unclear; the problem actually has nothing to do with whitespace so it's quite misleading. – AD7six Nov 14 '22 at 13:19
  • AD7six? If the problem "has nothing to do with whitespace," can you explain what the problem is? It would be essential to me. – GLEIPH GHIOTTO LIMA DE MENEZES Nov 16 '22 at 12:40
  • I don't know what the problem is, because the question doesn't explain it - but it's literally not "Git is ignoring whitespaces during merge by default" which is the premise of the asked question. – AD7six Nov 16 '22 at 18:15