{"id":120981,"date":"2024-12-14T09:45:59","date_gmt":"2024-12-14T07:45:59","guid":{"rendered":"https:\/\/prohoster.info\/blog\/novosti-interneta\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git"},"modified":"2024-12-14T09:45:59","modified_gmt":"2024-12-14T07:45:59","slug":"mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/news\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git","title":{"rendered":"mergiraf &#8212; strumento orientato AST per la fusione a tre vie in Git","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u00c8 stata pubblicata la versione 0.4 del progetto mergiraf, che sviluppa un driver per Git con l'implementazione della possibilit\u00e0 di fusione a tre vie. Mergiraf supporta la risoluzione di vari tipi di conflitti durante la fusione e pu\u00f2 essere utilizzato per vari linguaggi di programmazione e formati di file. \u00c8 possibile utilizzare mergiraf come chiamata separata per gestire i conflitti che si presentano durante l'uso di Git standard, oppure sostituire il gestore delle fusioni di Git per estendere le funzionalit\u00e0 di comandi come merge, revert, rebase e cherry-pick. Il codice \u00e8 distribuito sotto licenza GPLv3. La nuova versione include il supporto per i linguaggi Python, TOML, Scala e Typescript, oltre a ottimizzazioni delle prestazioni.    <\/p>\n<p>Di seguito viene fornita una descrizione dettagliata dei problemi risolti con l'ausilio di mergiraf:    <\/p>\n<p>Il software \u00e8 un esempio lampante di un sistema estremamente complesso. I sistemi complessi hanno una caratteristica comune: sono COMPLESSI e non ci si pu\u00f2 aspettare che il comportamento complesso desiderato emerga da solo, casualmente. Al contrario, questi sistemi evolvono nel tempo, passo dopo passo, e ogni mutazione viene attentamente verificata ad ogni fase. Per raggiungere questo obiettivo sono necessarie una struttura ben definita e strumenti appropriati. L'evoluzione di qualsiasi sistema complesso pu\u00f2 essere visualizzata come un albero orientato, dove la radice rappresenta un insieme vuoto di funzioni e ogni nodo, ad eccezione della radice, \u00e8 il risultato dell'applicazione di una mutazione al proprio genitore.     <\/p>\n<p>Nel contesto dei prodotti, ogni nodo \u00e8 chiamato \"versione\", che rappresenta un insieme specifico di funzioni e anti-funzioni. Qualsiasi modifica di questo insieme \u00e8 considerata una mutazione, formando un arco nel nostro grafo orientato aciclico. Queste funzioni sono per loro natura astratte; non riflettono direttamente i modi di funzionamento dei sistemi fisici, ma dimostrano piuttosto come gli agenti razionali percepiscono l'utilit\u00e0 di questi sistemi. Per tradurre concetti in implementazioni reali, \u00e8 necessario rimboccarsi le maniche e immergersi nei dettagli *sufficientemente* a basso livello, in un linguaggio che consenta di esprimere e spiegare esattamente come funziona tutto. Nello sviluppo software, questi dettagli a basso livello sono solitamente rappresentati dal codice sorgente.    <\/p>\n<p>Per riportare gradualmente il codice sorgente in uno stato che mostri il comportamento richiesto e documentare come ci sono arrivati, i programmatori rappresentano il loro lavoro in termini di snapshot e changeset. Uno snapshot rappresenta uno stato specifico del prodotto con tutti i dettagli a basso livello, mentre un changeset indica il passaggio tra gli snapshot. Di solito, gli snapshot sono generati da singoli changeset ai loro genitori, quindi questi snapshot sono quasi sempre contrassegnati da ci\u00f2 che fanno i changeset che li hanno creati, ed \u00e8 per questo che questi termini sono frequentemente usati in modo intercambiabile.     <\/p>\n<p>A volte esistono snapshot ottenuti a seguito di pi\u00f9 passaggi \u2014 fusioni di commit. \u00c8 difficile lavorare con essi, quindi di solito vengono evitati. I moderni sistemi di controllo versione open source, come Git, offrono funzionalit\u00e0 piuttosto basilari per gestire i flussi di lavoro di sviluppo. Consentono agli sviluppatori di organizzare snapshot sotto forma di grafi aciclici orientati, di annotarli con commenti e di cambiarne l'ordine se necessario.     <\/p>\n<p>Questa funzionalit\u00e0 consente agli sviluppatori di scrivere una storia del progetto semanticamente significativa, fondamentale per il debugging e per rispondere a domande come \u00abPerch\u00e9 \u00e8 stata introdotta questa sottile caratteristica (ad es., variabile)?\u00bb, \u00abQual \u00e8 stata approssimativamente la mia percentuale di contributo a questo progetto?\u00bb, \u00abChi \u00e8 stato compromesso dall'introduzione di un backdoor e quando?\u00bb, \u00abQuale modifica a basso livello ha rotto questa funzione (anche se non dovrebbe, abbiamo controllato tutto!?)\u00bb    <\/p>\n<p>I sistemi di controllo versione integrano questo concetto di ramo \u2014 un concetto a basso livello che significa semplicemente un frammento continuo della storia a basso livello del progetto, semanticamente significativo per lo sviluppatore. I rami sono solitamente utilizzati per implementazioni specifiche di funzionalit\u00e0, e talvolta vengono creati pi\u00f9 rami per diversi candidati all'implementazione della stessa funzionalit\u00e0. Utilizzando flussi di lavoro con ramificazione (che sono in realt\u00e0 la norma e lo standard di sviluppo, usati ovunque e in qualsiasi luogo), ogni singolo sviluppatore pu\u00f2 gestire efficacemente molti rami in conflitto del progetto, ognuno dei quali differisce per grado di prontezza o qualit\u00e0. Questo consente agli sviluppatori di combinare i risultati dei propri sforzi e di quelli degli altri senza dover riscrivere tutto a mano ogni volta.     <\/p>\n<p>Di solito si crea un ramo principale, che rappresenta il prodotto \u00abufficiale\u00bb, da cui si ramificano rami laterali per ogni funzionalit\u00e0, che vengono regolarmente (idealmente \u2014 dopo ogni commit) sincronizzati con il ramo principale, consentendo agli sviluppatori di lavorare con la versione pi\u00f9 aggiornata del prodotto e allo stesso tempo di implementare funzionalit\u00e0 su cui stanno attualmente lavorando, rilevando i problemi derivanti dalle azioni di altri sviluppatori il prima possibile.    <\/p>\n<p>Quando si tenta di combinare le funzionalit\u00e0 di diversi snapshot (che \u00e8 semplicemente la ricerca di un antenato comune e l'applicazione sequenziale dei cambiamenti generati su un altro, questa operazione \u00e8 chiamata rebase, mentre la fusione \u00e8 quasi come un rebase, ma struttura il grafo dei commit in modo diverso, rendendolo cos\u00ec scomodo da manipolare; per questo motivo si tende ad evitare le fusioni a favore dei rebase), possono sorgere problemi. I moderni sistemi di controllo versione (VCS) utilizzano algoritmi interni per unire le modifiche, che semplicemente dividono i file in singole righe, trattando ogni riga come un simbolo, e i file come loro sequenze, quindi applicano algoritmi per unirli, originari della bioinformatica.     <\/p>\n<p>Purtroppo, questa rappresentazione riga per riga del codice sorgente non ha niente a che fare con il suo contenuto. L'unico suo pregio \u00e8 che \u00e8 semplice e universale. L'incongruenza porta a conflitti, rappresentando una fonte costante di mal di testa per gli sviluppatori. Risolvere i conflitti richiede agli sviluppatori di esaminare attentamente entrambe le versioni del codice, non solo le sezioni contrassegnate dall'algoritmo di confronto riga per riga come 'modificate' o 'conflittuali', ma forse anche l'intero progetto.     <\/p>\n<p>Lo sviluppatore deve comprendere le modifiche, scrivere manualmente il codice unito e risolvere eventuali incongruenze. I problemi aumentano notevolmente quando l strumenti a livello di riga identifica scorrettamente le modifiche, cosa che accade spesso con grandi cambiamenti, comprese le modifiche banali come il riformattamento del codice. Se le modifiche successive non possono essere applicate al codice unito manualmente, la situazione diventa un incubo totale. Nonostante i casi allarmanti, nella maggior parte dei casi l'algoritmo a livello di riga funziona, specialmente se gli sviluppatori si sforzano attivamente di non creargli problemi. Uno dei modi per minimizzare questi problemi \u00e8 l'obbligo di elaborare i sorgenti con strumenti di canonicalizzazione, come black.    <\/p>\n<p>Naturalmente, la soluzione corretta per casi spaventosi (e non solo per quelli, l'algoritmo riga per riga \u2014 \u00e8 un'euristica, che pu\u00f2 portare in modo banale a codice non funzionante; ad esempio, un sviluppatore ha rinominato una variabile mentre un altro stava scrivendo un nuovo codice che utilizzava quella variabile, non ci sar\u00e0 conflitto di merge\/rebase, ma il risultato diventer\u00e0 non funzionante) \u2014 \u00e8 l'uso di un modello interno corretto.     <\/p>\n<p>Sebbene la ricerca in questo campo sia in corso da circa 30 anni e abbia portato alla creazione di diversi prodotti commerciali proprietari, fino a poco tempo fa queste ricerche non erano state trasformate in prodotti pratici applicabili a codice aperto. La maggior parte delle soluzioni di software libero ha iniziato a svilupparsi all'inizio degli anni 2010, ed era focalizzata principalmente sul linguaggio Java.    <\/p>\n<p>La realizzazione free pi\u00f9 notevole di quel periodo, GumTree, \u00e8 stata creata da un ricercatore con una formazione accademica, \u00e8 scritta in Java, ha una propria rappresentazione interna astratta, antecedente a treesitter, e ha backend sia basati su treesitter che su altri strumenti per il parsing del codice sorgente in rappresentazioni astratte. Questo sistema \u00e8 capace solo di generare (sotto forma di log di eventi testuali, esiste anche un'API che pu\u00f2 essere richiamata facilmente da qualsiasi linguaggio di programmazione che ha binding a Java) e di visualizzare modifiche. Tuttavia, per unire modifiche, cos\u00ec come per visualizzare i file diff generati, non \u00e8 applicabile out-of-the-box (s\u00ec, \u00e8 probabile che il caricamento dei diff possa essere implementato tramite l'API).    <\/p>\n<p>La realizzazione pi\u00f9 giovane e pi\u00f9 praticabile di difftastic \u00e8 scritta in Rust, \u00e8 basata su treesitter e si concentra sulla generazione di diff evidenziati in console. Questo sistema \u00e8 anch'esso dedicato alla visualizzazione dei diff e non ha come obiettivo l'unione delle modifiche o l'applicazione di patch.    <\/p>\n<p>Recentemente \u00e8 emerso e si sta sviluppando attivamente il progetto mergiraf. Questo strumento scritto in Rust (occupa 21 MiB!) si basa anche su treesitter, che \u00e8 diventato uno standard per i parser di grammatiche context-free negli strumenti di sviluppo, tanto quanto LLVM lo \u00e8 per l'ottimizzazione delle rappresentazioni a basso livello delle istruzioni. A differenza dei concorrenti, mergiraf fornisce funzionalit\u00e0 non per la generazione di diff, ma per la risoluzione automatica dei conflitti di merge. Nascosto, mergiraf utilizza per la generazione dei patch un'implementazione dell'algoritmo utilizzato in GumTree e per l'applicazione un'implementazione dell'algoritmo utilizzato in spork, adattati per le strutture treesitter.     <\/p>\n<p>La serializzazione delle patch in file che possono essere applicati in seguito, purtroppo, non \u00e8 stata implementata (ma \u00e8 molto probabile che possa essere realizzata tramite il parsing dei log degli eventi generati da GumTree). Un altro modo promettente per applicare le differenze potrebbe essere il ricorso non a patch, ma alla funzionalit\u00e0 di refactoring dei server LSP, che pu\u00f2 aiutare nel rilevamento dei conflitti a livello di progetto. La visualizzazione \u00e8 supportata solo per i conflitti.    <\/p>\n<p>Esempio di lavoro: l'antenato comune \u00abbase.py\u00bb (indentazione con tabulazioni, riga extra all'inizio) foo = 1 def main(): print(foo + 2 + 3) \u00aba.py\u00bb (indentazione ancora con tabulazioni, 2 righe extra all'inizio invece di una, per la stampa di debug \u00e8 stata utilizzata la libreria icecream, \u00e8 stata aggiunta la classe \u00abbaz\u00bb: from icecream import ic foo = 1 def main(): ic(foo + 2 + 3) class baz: def __init__(self): \u00ab...\u00bb \u00abb.py\u00bb (la variabile \u00abfoo\u00bb \u00e8 stata rinominata in \u00abbar\u00bb, elaborato con \u00abblack\u00bb dopo le modifiche, con il risultato che l'indentazione \u00e8 stata convertita in spazi e le righe extra sono state rimosse): bar = 1 def main(): print(bar + 2 + 3) La chiamata .\/mergiraf merge .\/base.py .\/a.py .\/b.py -x a.py -y b.py -s base.py -o .\/res.py porta al seguente risultato from icecream import ic bar = 1 def main(): ic(bar + 2 + 3) class baz: def __init__(self): \u00ab...\u00bb. (Per la stampa di debug \u00e8 stata utilizzata la libreria \u00abicecream\u00bb, la variabile \u00abfoo\u00bb \u00e8 stata rinominata in \u00abbar\u00bb, elaborato con \u00abblack\u00bb dopo le modifiche, di conseguenza l'indentazione \u00e8 stata convertita in spazi e le righe extra sono state rimosse, misto di tabulazioni e spazi per l'indentazione, ma in forma consentita).    <\/p>\n<p>Qui si evidenzia un difetto dello strumento. Lo stile del documento \u00e8 solitamente configurato in file &#171;.editorconfig&#187;, e modifiche globali allo stile, come passare da tabulazioni a spazi e adottare lo stile black, come fatto in &#171;b.py&#187;, sono di solito accompagnate da modifiche nel file &#171;.editorconfig&#187;. Pertanto, per applicare in modo pi\u00f9 corretto tali modifiche, lo strumento dovrebbe avere un concetto per lo stile globale &#171;di default&#187; e saper importare le impostazioni da &#171;.editorconfig&#187;.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/www.opennet.ru\/opennews\/art.shtml?num=62402\">opennet.ru<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 mergiraf 0.4, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f Git \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f. Mergiraf \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0438\u0434\u043e\u0432 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u043f\u0440\u0438 \u0441\u043b\u0438\u044f\u043d\u0438\u0438 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 mergiraf \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u043e \u0448\u0442\u0430\u0442\u043d\u044b\u043c Git, \u0442\u0430\u043a \u0438 \u0437\u0430\u043c\u0435\u043d\u0430 \u0432 Git \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0441\u043b\u0438\u044f\u043d\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-120981","post","type-post","status-publish","format-standard","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 mergiraf 0.4, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f Git \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/news\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47mergiraf \u2014 AST-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f \u0432 Git | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 mergiraf 0.4, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f Git \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/news\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2024-12-14T07:45:59+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2024-12-14T07:45:59+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47mergiraf \u2014 Strumento orientato all'AST per la fusione a tre vie in Git | ProHoster","description":"\u00c8 stata pubblicata la versione 0.4 del progetto mergiraf, che sviluppa un driver per Git con implementazione della possibilit\u00e0 di fusione a tre vie.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/news\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47mergiraf \u2014 AST-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f \u0432 Git | ProHoster","og:description":"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 mergiraf 0.4, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f Git \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0451\u0445\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0441\u043b\u0438\u044f\u043d\u0438\u044f.","og:url":"https:\/\/prohoster.info\/it\/blog\/news\/mergiraf-ast-orientirovannyj-instrument-dlya-tryohstoronnego-sliyaniya-v-git","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2024-12-14T07:45:59+00:00","article:modified_time":"2024-12-14T07:45:59+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"120981","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 08:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2026-01-23 08:54:19","updated":"2026-01-23 08:54:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/120981","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=120981"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/120981\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=120981"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=120981"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=120981"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}