TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

What if Git worked with programming languages?

170 点作者 LukeEF超过 3 年前

43 条评论

mumblemumble超过 3 年前
I would maybe be interested in Git allowing you to plug in your own diff generators for different file types.<p>But I would not want Git itself trying to understand the contents of files. That seems to me to be an idea that lives on a misconception of the &quot;things programmers believe about names&quot; variety. Not every file in source control is source code. Not every programming language&#x27;s grammar maps to an abstract syntax tree. In some files, such as makefiles, the difference between tabs and spaces is semantically significant. Some languages (such as Fortran and Racket) have variable syntax. And so on and so forth.<p>So I think that we <i>really</i> don&#x27;t want the source control system itself trying to get too smart about the contents of files. That will inevitably make the source control system less compatible with the various kinds of things you might want to put into source control. And it will also make the source control system a lot more complicated than it would otherwise be, in return for a largely theoretical payoff.<p>But if we want to delegate the work of generating diffs off to other people, so that Git can allow for syntax or semantics-aware diffing without having to personally wade into that quagmire (and perhaps also allowing language communities to support multiple source control systems, a bit like how it works with LSP), that might be an interesting thing to experiment with.
评论 #28674731 未加载
评论 #28675652 未加载
评论 #28675235 未加载
评论 #28677623 未加载
afavour超过 3 年前
I do kind of love the idea of Git using ASTs instead of source code. It makes a ton of sense.<p>Even just in the immediate term I wish I could make Git(hub) tabs&#x2F;2 spaces&#x2F;4 spaces&#x2F;whatever agnostic. Seems crazy to me that in 2021 we still have to make opinionated choices across orgs about what to use... why can&#x27;t we pull the code down, view it in whatever setup we want, then commit a normalized version?<p><i>[whispers] this is actually something tabs allow you to do natively by setting custom tab widths in text editors but I&#x27;ve given up trying to sell people on tabs at this point and just want to be able to do my own thing</i>
评论 #28671124 未加载
评论 #28671043 未加载
评论 #28671454 未加载
评论 #28671494 未加载
评论 #28671201 未加载
评论 #28674849 未加载
评论 #28673057 未加载
评论 #28671130 未加载
评论 #28674702 未加载
评论 #28671107 未加载
mabbo超过 3 年前
Reading this article, I feel as though the author doesn&#x27;t deeply understand git.<p>git works on blobs of data, not files, and not lines of text. It doesn&#x27;t just happen to also work on binary files- that&#x27;s all it works on.<p>Now, if the author is suggesting that git-diff ought to have a language specific mode that parses changed files as ASTs to compare, now I&#x27;m interested. Let&#x27;s do that. I&#x27;ll help!<p>But git does not need to change how it works for that to happen. Git does not even need git-diff to exist to serve it&#x27;s main purpose.
评论 #28673751 未加载
评论 #28676554 未加载
评论 #28673589 未加载
评论 #28673561 未加载
评论 #28673524 未加载
评论 #28675208 未加载
评论 #28674189 未加载
评论 #28677605 未加载
评论 #28681818 未加载
nerdponx超过 3 年前
Storing AST instead of source code is one of the goals of the very interesting Unison programming language: <a href="https:&#x2F;&#x2F;www.unisonweb.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.unisonweb.org&#x2F;</a><p>Part of what&#x27;s nice about Git (and plain text in general) is that it&#x27;s the lowest common denominator for a lot of things. This is why traditional Unix tools are built oriented around streams of bytes. Text is a low level carrier protocol; you can encode almost anything in it, but you need to agree on some kind of format.<p>The good part is that you can use very very generic tools on almost arbitrary pieces of data. The bad part is that you might have to do a lot of parsing and re-parsing of the same data, and you have to contend with the dangers of underspecified formats.<p>Git follows the Unix tradition in this regard. As a result, it is nearly universal in what it can store. You can use it to store pretty much anything, but you are now at the lowest common denominator of support for any particular data format.<p>Git-for-ASTs will no longer have this universality property, but will gain a lot more power in the covered domain. This is a design tradeoff.<p>One thing that&#x27;s nice about Git is that you can specify arbitrary diff drivers with the &quot;attributes&quot; system. So even if the Git database is storing plain text, your diff driver can parse your source code into ASTs and present AST diffs to you when you run `git diff`. Perhaps more impressive, you can configure custom <i>merge</i> drivers, so you can (theoretically) implement semantic merging of ASTs right inside Git.<p>There are probably some fundamental limitations of this system, because the underlying data is still stored as blobs of bytes. But you can get pretty far as long as you don&#x27;t mind parsing and re-parsing the same text over and over.
评论 #28673258 未加载
Jensson超过 3 年前
I don&#x27;t see how this could ever work on evolving languages, different GIT versions would produce different commits and read commits differently based on the latest C++ standard. This would potentially lead to version control bugs where different GIT versions creates different results from the same commit, that is horrible, version control needs to be 100% bug free in that regard.<p>The only reasonable application would be to use a language AST parser to better identify relevant text diffs, but the commits still needs to be stored as text.
评论 #28673556 未加载
评论 #28673562 未加载
评论 #28673572 未加载
Karellen超过 3 年前
`git` generally doesn&#x27;t work with lines of text. Mostly it works with opaque file blobs and directory trees.<p>`git diff` and `git merge` work with lines of text <i>by default</i> - but they don&#x27;t have to. You can supply your own `diff` and `merge` tools with the `difftool.*` and `mergetool.*` config options, try them out with `git-difftool` and `git-mergetool` commands, and set the default with the `git.diff` and `git.merge` config options.<p>If someone wanted to create AST-based diff and merge tools for a given language, they could be plugged right into the existing `git` infrastructure and it would work with them absolutely fine.
评论 #28671285 未加载
评论 #28671665 未加载
评论 #28671375 未加载
评论 #28671366 未加载
评论 #28671679 未加载
评论 #28671509 未加载
评论 #28672492 未加载
评论 #28671672 未加载
zomglings超过 3 年前
I maintain a free&#x2F;open source project that does exactly what the author asks for: <a href="https:&#x2F;&#x2F;github.com&#x2F;bugout-dev&#x2F;locust" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;bugout-dev&#x2F;locust</a>.<p>Our tool uses git as the foundation of its functionality. It superimposes git diffs on top of ASTs.<p>It is insanely powerful.<p>For example, we use it to power semantic code search and current support Python, Javascript, and Java. We generate a JSON object describing the AST differences between initial and terminal commits on GitHub PRs. A full text search on the JSON objects performs surprisingly well when we want to answer questions like, &quot;When did we add dateutils as a dependency?&quot; or &quot;When did we last change the &#x2F;journals handler on the API?&quot;<p>The Python integration currently sees the most use but if you are interested in other languages, we would be happy to support it.<p>Do drop me a DM if you want help getting started with Locust.
tombert超过 3 年前
I would definitely support a Lisp-centric Git.<p>Whenever I do Clojure, something that can get difficult when working with multiple people is how the parentheses&#x2F;brackets&#x2F;braces stack up, especially when everyone seems to have different opinions on how that works. As a result, if you&#x27;re not careful, when there&#x27;s a merge conflict you can have a ton of extra parentheses, which can be irritating to debug.<p>Obviously this is at some level an issue inherent to Lisps (and to be clear, I love Lisps, and these small headaches are worth it), but I think problems like that could be reduced if our source controls were aware of the ASTs.
评论 #28679592 未加载
评论 #28675344 未加载
ClassAndBurn超过 3 年前
Git is designed to require human oversight. This is usually a feature, but in recent years has become a bug with things like GitOps.<p>It&#x27;s important to remember that Git is a terrible database because of its lack of semantic structure. All conflicts require a human who does have to context. This is why almost no one builds a system that uses Git as a two way interface. And when they do, its via Github Pull Requests (which go to humans) and not Git itself.<p>In all, this makes it a wonderful general purpose shared filesystem. And that&#x27;s about it.
cormacrelf超过 3 年前
Counterpoint: a quick google reveals diffsitter: <a href="https:&#x2F;&#x2F;github.com&#x2F;afnanenayet&#x2F;diffsitter" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;afnanenayet&#x2F;diffsitter</a><p>The output could be a lot more compact, it could do better at adding context (in the same way <a href="https:&#x2F;&#x2F;github.com&#x2F;romgrk&#x2F;nvim-treesitter-context" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;romgrk&#x2F;nvim-treesitter-context</a> does, etc), but if you&#x27;re interested in this it&#x27;s really within reach, go help out.<p>I wonder if you can use it for automerge yet.
tomxor超过 3 年前
&gt; The fact that git works on lines of text [...] we could be looking at the alterations to the abstract syntax tree.<p>Fundamentally git does not operate on text, it operates on files (content addressed SCM not a ledger of text diffs); diffs are generated upon request between arbitrary merkel trees. So there is no need to implicate git in such a tool, it can be independent:<p><pre><code> GIT_EXTERNAL_DIFF When the environment variable GIT_EXTERNAL_DIFF is set, the program named by it is called to generate diffs, and Git does not use its builtin diff machinery. For a path that is added, removed, or modified, GIT_EXTERNAL_DIFF is called with 7 parameters: path old-file old-hex old-mode new-file new-hex new-mode</code></pre>
maweki超过 3 年前
Working on the AST is quite an interesting idea, until your comments aren&#x27;t in the AST and you want to commit a syntax error of work in progress.<p>Not to mention changing ASTs (while maintaining concrete syntax) in different versions of the language.
cies超过 3 年前
&gt; Structure editors haven&#x27;t really taken off yet despite several historical and contemporary attempts.<p>This is a nice contemporary one:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;projectional-haskell&#x2F;structured-haskell-mode" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;projectional-haskell&#x2F;structured-haskell-m...</a><p>Lisps also have all kinds of options available in Emacs, but it is more special to see this outside of the land of s-expressions.
shoo超过 3 年前
There&#x27;s a good blog post about auto-merging JSON&#x2F;XML structured data files (for game content) on the bitsquid blog from 2010:<p>&gt; having content conflicts is no fun either. A level designer wants to work in the level editor, not manage strange content conflicts in barely understandable XML-files. The level designer should never have to mess with WinMerging the engine&#x27;s file formats.<p>&gt; And conflicts shouldn&#x27;t be necessary. Most content conflicts are not actual conflicts. It is not that often that two people have moved the exact same object or changed the exact same settings parameter. Rather, the conflicts occur because a line-based merge tool tries to merge hierarchical data (XML or JSON) and messes up the structure.<p>&gt; In those rare cases when there is an actual conflict, the content people don&#x27;t want to resolve it in WinMerge. If two level designers have moved the same object, we don&#x27;t really help them address the issue by bringing up a dialog box with a ton of XML mumbo-jumbo. Instead, it is much better to just pick one of the two locations and go ahead with merging the file. Then, the level designers can fix any problems that might have occurred in the level editor -- the right tool for the job.<p>-- <a href="http:&#x2F;&#x2F;bitsquid.blogspot.com&#x2F;2010&#x2F;06&#x2F;avoiding-content-locks-and-conflicts-3.html" rel="nofollow">http:&#x2F;&#x2F;bitsquid.blogspot.com&#x2F;2010&#x2F;06&#x2F;avoiding-content-locks-...</a>
CodeIsTheEnd超过 3 年前
I don&#x27;t understand why GitHub hasn&#x27;t solved the issue of diffs starting with a &#x27;}&#x27; (or &#x27;)&#x27; or &#x27;end&#x27;). Just slide the diff over while it starts with a closing token! I suppose it&#x27;s an artifact of the diffing algorithm, but aren&#x27;t there better diffing algorithms, even built-in within git?<p>This is by far the most obvious example of &quot;git doesn&#x27;t understand programming languages&quot;, but it also seems like the most straightforward to fix.
评论 #28676579 未加载
评论 #28676530 未加载
aardvark179超过 3 年前
I’ve done quite a lot of work on version management on structured data (in my case this was for a version managed GIS database) and it’s not an easy problem, and is likely even harder with something like an AST that is generated from a text file and so does not preserve the identity of nodes. I’m not saying that it’s impossible, but it is more work and requires more tooling around it than people think, and it keeps coming up here and other places as a, “really good idea.”
ufo超过 3 年前
I&#x27;m trying to remember the citation, but I remember seeing a presentation once from someone who studied this and they said that the thing that worked best was a hybrid approach: use structured diff at the top level of the program (modules &#x2F; methods) but use line-based for statements and expressions. According to them, the structured diff can give unintuitive results if applied at the lowest syntactic levels.
alkonaut超过 3 年前
I’d give anything just to get a few basic merge modes. For example “this file can treat two one line additions as unordered”.<p>So any shared append-only file (a change log, an enumeration,…) doesn’t automatically conflict.<p>Syntax aware diffing would be great too, but I’d take something much simpler. For syntax aware stuff I’d love something that could tell semantic changes from noise.
auscompgeek超过 3 年前
Note that you can specify a custom merge driver for different file types using a combination of gitattributes and git-config: <a href="https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Customizing-Git-Git-Attributes#_merge_strategies" rel="nofollow">https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Customizing-Git-Git-Attribute...</a>
kazinator超过 3 年前
The blogger does not understand Git, fundamentally.<p>Git does does not work with text. It stores snapshots of artifacts.<p>The diffs that you see when you use the various commands like git log -p are recovered from the snapshots, when those artifacts happen to be text files.<p>Git absolutely works with texts when you connect it with external representations and tooling, such as when you &quot;git format-patch&quot; and then &quot;git am&quot; to import that; and the rebasing workflows obviously have textual merging with conflict resolution. Still, that seems like something that could be externalized. A language-specific three-way-diff tool can handle a merge by parsing all three pieces and working with ASTs. It&#x27;s something that could be developed later, yet still work with your old commits.<p>There is this: <a href="https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-mergetool" rel="nofollow">https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-mergetool</a><p>No idea how well it works.
mangecoeur超过 3 年前
Interesting they mentioned Jupyter Notebooks but not NBDime <a href="https:&#x2F;&#x2F;github.com&#x2F;jupyter&#x2F;nbdime" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;jupyter&#x2F;nbdime</a> which is a Jupyter plugin specifically to address this problem. Without it, diffing notebooks is not feasible.
Smaug123超过 3 年前
I&#x27;m surprised they didn&#x27;t mention Unison (<a href="https:&#x2F;&#x2F;www.unisonweb.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.unisonweb.org&#x2F;</a>), whose big idea is an immutable content-addressable store of ASTs. I really hope it changes everything.
评论 #28674603 未加载
g051051超过 3 年前
Back in the early 2000&#x27;s Visual Age for Java allowed you to version individual methods. Since Visual Age for Java was derived from Visual Age for Smalltalk (and was actually written in Smalltalk) I suppose it inherited the capability from there.
评论 #28685232 未加载
hardwaregeek超过 3 年前
I&#x27;ve wanted this for a while, but I will say there&#x27;s some caveats. Sometimes I want to commit just as a &quot;it&#x27;s the end of the day, I want to leave, here&#x27;s a code dump&quot;. I suppose you could have multiple tiers of code saving.<p>I&#x27;ve also wondered about whether you could do code analysis with time as a dimension. If you can analyze the evolution of the code and pull old implementations, what can you do? Autocomplete is a good example, as it can pull previous patterns you&#x27;ve used. Maybe some way to tell the programmer &quot;hold up, you&#x27;ve made this mistake before, don&#x27;t do it again&quot;? I&#x27;m not sure.
评论 #28673678 未加载
raxxorrax超过 3 年前
Theoretically it might work, but I don&#x27;t think I am too fond of the idea. I used git pull to completely waste my source and it would have been nice for git to have more intelligence here, but in the end I think some of its success lies in its simplicity.<p>SVN isn&#x27;t too bad and not too much of a difference to git if you use a central repository anyway. The main neat thing was to just have one hidden folder, not in every subdirectory.<p>Git would also need the ability to transform from AST to source for every language. A bit unrealistic and there is no benefit to it. Could also do that with Assemblies and some meta info for the decompiler.
jakeinspace超过 3 年前
I think the only useful way to implement AST-level diff&#x2F;merge for non-trivial codebases would require the compiler to provide the parsed AST, since per-file ASTs would lack a lot of context. You could also ask the user to provide a separate file or files that describe the code topology, but why bother when the compiler can spit out an AST itself? A diff tool which targets a few of the bigger build systems (CMake, Maven, Gradle) and compilers might work, and could worry about small build environments after gaining momentum.
jpitz超过 3 年前
Didn&#x27;t the VisualAge IDEs do this with their built-in version control? This was 20 years ago, and I seem to remember that the version control was at the method level, not file level.
ozim超过 3 年前
I feel this is just an example of &quot;worse is better&quot; and whole proposition as interesting but totally not practical and I would not like for GIT to go anywhere near that idea.
olodus超过 3 年前
Ever since I learned about Git merge strategies and wrote a very basic one myself, I&#x27;ve been wanting to write one that syntaxticly understands a bit of the test framework code we use at work. It is super annoying when you copy a test because you want to vary a very specific case and gig gets all confused about what code is and isn&#x27;t the same.<p>(yeah I know I should break out the copied part but who always has time for that)
aidenn0超过 3 年前
The problem with a tool that depends on structured data is that it only works with structured data.<p>Of course the problem with a tool built for unstructured data is that it&#x27;s dumber than it need be, and when you do treat the data as structured, it&#x27;s ad-hoc and often buggy.<p>When talking about how &quot;powerful&quot; a tool is, there&#x27;s always this tension between structured and unstructured.
skybrian超过 3 年前
If you’re interested in this sort of thing you might want to look at Dolt (for sharing databases in a git-like way) and Pijul, which records diffs explicitly, rather than calculating them on the fly.<p>I wonder if there might be a clever way to encode source code in a Dolt database? Maybe each function should be a record?
评论 #28673918 未加载
bialpio超过 3 年前
This made me think of Unison: <a href="https:&#x2F;&#x2F;www.unisonweb.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.unisonweb.org&#x2F;</a><p>Discussion: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=27652677" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=27652677</a>
iso8859-1超过 3 年前
This is on the <a href="http:&#x2F;&#x2F;lamdu.org" rel="nofollow">http:&#x2F;&#x2F;lamdu.org</a> roadmap.
kitplummer超过 3 年前
I&#x27;m just a bit more &quot;generally&quot; curious. Is `git` being the _only_ DVCS a good thing? Not to say that `hg` or `darcs` don&#x27;t exist, just that the hub on top of git has pushed us in a singular direction.<p>I would like to see, at least academically, something more.
评论 #28673242 未加载
elif超过 3 年前
It sounds inspirational and revolutionary but the longer I think about it, the less utopian it feels. The idea of forgetting about pieces of code or how things are linked.<p>Files also provide an opportunity to purposefully communicate organizational intent.
WalterBright超过 3 年前
I&#x27;m fine with the line oriented nature of git. I wouldn&#x27;t want to be confronted with problems due to the constantly shifting nature of languages vs whatever plugin exists for them on git. Even C is constantly changing.
gumby超过 3 年前
Shared (concurrent) code editors might work better if their CRDT&#x2F;OT model worked at that level.<p>Not that I really want to edit code in a shared environment (editing documents that way is bad enough), but just musing…
ghoward超过 3 年前
I&#x27;m actually working on a VCS based on this idea and on tracking changes to binary files based on their structure as well. (It turns out that the same techniques work for both.)<p>AMA and please give me feedback!
atonalfreerider超过 3 年前
Self-promote: Primitive does AST diffing and represents the changes graphically<p>primitive.io
jcrites超过 3 年前
I’ve had loosely similar ideas before. The basic idea is to make the compiler tool chain aware of diffs, and help scrutinize and implement them. Refactoring suggestions could be included with the diff.<p>For example, say you’re dependending on a module and it renamed a class&#x2F;method&#x2F;trait&#x2F;macro&#x2F;constant&#x2F;whatever. A synchronous method has become a sync or vice versa.<p>The diff could include programmatic instructions for consumers to apply to their code bases switching them over to the new method. This could be as simple as semantically changing the name used, or in the case of changing sync to a sync it could add `await` in the appropriate spot.<p>There’s no limit to how complex the rewrite rules could be. You could totally reorganize the parameters to a function and ship that refactoring, or even add a parameter along with the default code necessary to provide it.<p>Unlike the author I don’t think code in Git will likely ever move beyond source, plus the refactoring instructions needed to update a change from a dependency — perhaps a macro-like syntax.<p>Too much text manipulation is required from source control for me to conceive of it being anything but human programming text in a future I can imagine. Machines can already parse it; there doesn’t seem to be a compelling reason to store some other kind of structure.<p>Refactoring wouldn’t need to be any special Git extension, just a file accompanying the commit with instructions for the language tool chain.<p>Your IDE or CLI could walk you through interactively everywhere it’s getting applied, or you could apply all and review the result in your app that consumes the module.<p>This would also open up security risks from accepting diffs from dependencies and applying their refractors, but unless modules are sandboxed quite well that’s a risk you take with updating dependencies anyway. And you can always scrutinize the refactoring-diff manually after it runs before accepting it.<p>The industry would probably standardize onto the notion that a change that requires running automated room factoring from a dependency across your codebase is a major version change; in other words a breaking or backwards incompatible change, just one that’s much easier to upgrade to.<p>Languages with macros or other programmatic transformers would be well suited to this concept I think.<p>Maybe Rust macros could be enhanced for the purpose to pattern match over an existing codebase somehow: not just the macro invocation point, but anywhere, e.g., a given trait or function is used; and then the output of the macro would not feed into the next stage of the compiler step but would instead result in rewriting code on disk to produce a diff that you examine and apply to your code.<p>A capability like this would make it much easier to manage large aggregate code bases consisting of many dependencies. OSS package maintainers or infrastructure providers at companies could ship nominally backwards -incompatible changes that are still actually compatible when you run the macro transformer that updates the code that uses them.<p>For a simple example, imagine that `foo()` was previously a function and the implementation chooses to add some optional parameters or those with default values and change it into a macro `foo!()`. The accompanying transformer would semantically identify references to `foo()` and make the necessary updates. You could rename global constants or traits or other code elements this way.<p>Consider the way in which Google Guava has had to evolve over time. A number of its features have become part of the Java language, and thus the classes deprecated and removed gradually. With a compiler facility like what I am describing, users of Guava could run the transformer to migrate older could bases that use methods like Guava’s `Preconditions.checkNotNull(Object, message))` to use Java’s now-standard `Objects. requireNonNull (T obj, String message)`. Because the maintainers of Guava wanted to keep it modern, current, avoid redundancy, and designed in the best way that they knew how, they made a number of breaking changes for which the project lead later apologized [1]. Most changes wouldn’t have been be painful if accompanied by automated refactoring.<p>You could allow the transformer to produce code that still needs work from humans to finalize and compile. In that case it could change as much as it’s able and leave instructions at each call site.<p>At my company we have bots that submit proposed code changes to our codebase that need to be taken over as author by a human, reviewed, sometimes lightly edited, and shipped, and they work quite well. One bit finds unused code and submits diffs to remove it if it’s been in the code repository long enough. Another detects when launch experiments have been at 100% all on one treatment for a long period of time (meaning the feature has launched) and submits code removing the experiment check. The latter sometimes require removes surrounding code that would subsequently become unused from removing the experiment check.<p>These have provided meaningful value in helping keep the codebase tidy and I look forward to more automation like this in the future, including diff-aware compilers and refactoring tools.<p>[1] <a href="https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;java&#x2F;comments&#x2F;mr03mi&#x2F;comment&#x2F;guk8482&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;java&#x2F;comments&#x2F;mr03mi&#x2F;comment&#x2F;guk848...</a>
jrm4超过 3 年前
What if Programming Languages worked with Lines of Text?
lamontcg超过 3 年前
This has been posted before
vxNsr超过 3 年前
Is it just me or is he describing an IDE with source control?