Git Product home page Git Product logo

jj's People

Contributors

antoinecezar avatar arxanas avatar avamsi avatar bnjmnt4n avatar chooglen avatar dbarnett avatar dependabot[bot] avatar elasticdog avatar emesterhazy avatar emilykfox avatar essiene avatar ilyagr avatar jonathantanmy avatar jsoref avatar julienvincent avatar martinvonz avatar mforster avatar mlcui-corp avatar necauqua avatar philipmetzger avatar pingiun avatar poliorcetics avatar ralith avatar samueltardieu avatar talpr avatar thoughtpolice avatar torquestomp avatar tp-woven avatar yuja avatar zummenix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jj's Issues

support for signed commits

Expected Behavior

jj close -S would sign the commit enabling compatibility with workflows which require verified commits

Actual Behavior

There currently is no support for signing commits

Implementing this feature will require careful consideration given how much jj appears to silently create commits under the covers, since some workflows will prompt for the GPG keyphrase either on every commit action, or every so often if the gpg-agent is running

Specifications

Rework revset operators

Mercurial has a :: operator, which returns the ancestors when used as a prefix (::foo), descendants when used as a suffix (foo::), and the intersection of the two when used as infix (foo::bar). I like that and I tried to extend it by using the same operator for parents and children. That's how I ended up with :foo meaning "parents of foo" and foo: meaning "children" of foo. However, it hasn't worked very well in practice.

One problem with it is that we don't have a simple way of saying "N generations back/forward". Git and Mercurial have foo~10 for saying "ten generations back from foo". However, because we use : as either prefix or suffix, 11:22 becomes ambiguous (is it 22 generations after a commit with hex prefix 11 or 11 generations before a commit with hex prefix 22?).

Another problem, which is just small annoyance, is that by using : as prefix for the very common case of specifying parents, we make it harder to go one more step back, because the user needs to move the input cursor to before the symbol. For example, if you've entered jj diff -r :@ and realized that you wanted to go one more step back, you need to move the cursor left before you can insert an extra :.

So, we should probably switch to foo~ for "parents of foo" and maybe foo+ for "children of foo". Then we free up : to be used in other operators. We could probably use : for Mercurial's :: operator (we don't want its : operator). Maybe we should also support Git's .. operator (not sure about ... -- I almost never want it myself).

I think it would be nice to also have a syntax for a range of generations. Perhaps foo[-5:2] could mean "from 5 generations back to 2 generations forward from foo".

I wonder if we should use an operator for commit ID and/or change ID. Maybe =abc could be the commit ID with prefix abc and %abc could be the change ID with prefix abc. I'm not sure it's worth spending two characters on that. We should definitely have revset functions for it.

Remove support for changeset evolution

Since I enabled auto-rebase after every command ~5 months ago (commit 6a5f9dd), I have never used jj evolve. I therefore plan to remove support for evolution in general (not just the command). I think that will make both UX and code simpler. We currently have three kinds of DAGs: the commit graph, the obsolescence graph, and the operation graph. Removing one of them should be positive.

My repo currently has ~8.5k hidden heads and even though I haven't noticed it causing any slowness, I think we should be able to make things faster by not having all those extra heads that we mostly ignore.

We'll want to have a replacement for jj obslog. I hope to do that based on the operation log. jj op log --change <change-id> or something like that would be conceptually similar to jj log <path> (which currently doesn't exist :)) in that it filters the log. However, diffing repo states is somewhat slow, so we'll probably need to do some indexing to make it useful.

Of course the big difference between evolution and auto-rebase is that the latter is local. It won't handle all cases where developers cooperate in developing a stack of commits. However, I plan to make it so at least simple cases will be handled:

  • When a Git ref has been rewritten on a remote, we rebase any local descendants.
  • When a change has been rewritten on a remote, we rebase any local descendants. This will of course require support for exchanging change ids, so it won't work with a Git remote. However, we can probably get some benefit by extracting Gerrit Change-Ids and similar from commit messages and using them as change id.

Splitting working copy seems broken (in a --git-repo=. repo)

Interested to see a VCS tool compatible with Git, I decided to play with it, starting with this bit from the docs:

With Jujutsu, you'd instead use jj split to split the working copy commit into two commits

I did jj init --git-repo=. in a checkout of this very repo and edited two files:

% jj st
Parent commit: 03e6b8c0e6a4 working_copy: take `Tree`, not `CommitId`, as argument to `check_out()`
Working copy : d6382403c415
Working copy changes:
M README.md
M rustfmt.toml

Now I run jj split. Say I want to commit rustfmt.toml first, so I copy README.md left-to-right in Meld and enter the obvious descriptions and it seems to work:

% jj split
First part: 62cb2d07bc52 first part
Second part: 949b4659aee9 second part
Working copy now at: 949b4659aee9 second part

Expected Behavior

Working copy actually being at 949b4659aee9 like the message said?

Actual Behavior

The log and status command act like the split did not happen:

% jj status
Parent commit: 03e6b8c0e6a4 working_copy: take `Tree`, not `CommitId`, as argument to `check_out()`
Working copy : 16178fc092a1 first part
Working copy changes:
M README.md
M rustfmt.toml
% jj log
@ 16178fc092a1 e612ec30d5df [email protected] 2022-02-18 01:06:53.000 +03:00
| first part
o 03e6b8c0e6a4 37df45dd7108 [email protected] 2022-02-12 23:46:38.000 -08:00 main
| working_copy: take `Tree`, not `CommitId`, as argument to `check_out()`

The split commits do exist:

% jj show 62cb2d07bc52
Commit ID: 62cb2d07bc52b1345cced9acf003c73e84435086
Change ID: e612ec30d5df4d2b848c81d9f7078a7b
Author: Greg V <[email protected]> (2022-02-18 01:06:53.000 +03:00)
Committer: Greg V <[email protected]> (2022-02-18 01:12:57.000 +03:00)

first part

Modified regular file rustfmt.toml:
   1    1: max_width = 10069
   2    2: wrap_comments = true
   3    3: format_strings = true
   4    4: error_on_line_overflow = true
    ...

but are seemingly just lost from the jj log perspective.
jj diff and equivalently jj show 16178fc092a1 (the hash at the top of the log) show both changes together, i.e. what was there before the split, but with the same "first part" description as the actual first part (62cb2d07bc52). But the hash is new.

Looking at the git repo, actually the real first part is committed.

% g log --oneline | head
62cb2d0 first part
03e6b8c working_copy: take `Tree`, not `CommitId`, as argument to `check_out()`

And after fiddling with the git CLI (no write commands, only viewing the log) the jj log is messed up? o_0

@ 16178fc092a1 e612ec30d5df [email protected] 2022-02-18 01:06:53.000 +03:00    divergent
| first part
| o 62cb2d07bc52 e612ec30d5df [email protected] 2022-02-18 01:06:53.000 +03:00    HEAD@git divergent
|/  first part
o 03e6b8c0e6a4 37df45dd7108 [email protected] 2022-02-12 23:46:38.000 -08:00 main
| working_copy: take `Tree`, not `CommitId`, as argument to `check_out()`

Maybe I misunderstood something but it sounds like a bug?

Steps to Reproduce the Problem

(above โ€” I don't think steps should be below the story)

Specifications

  • Version: 03e6b8c
  • Platform: FreeBSD -CURRENT

Add a TUI for editing diffs

Surprisingly, there doesn't seem to be a good TUI tool for editing diffs. We need this for jj touchup, jj split, etc. We want a tool that can present the diff and let the user edit the right side of it. It should ideally support diffing directories. vimdiff might be the closest, but it doesn't support directories by default (it seems you need to install some plugin) and it's not intuitive.

Figure out why getting default branch from remote is unreliable

Something about how we get the default branch from the remote causes the tests to be unreliable. They have failed on Windows and Ubuntu so far. I have not gotten them to fail on Debian. I suspect it's related to cloning from a local-disk remote. The Remote::default_branch() call has failed for me outside of tests in many different ways:

  • Error { code: -3, klass: 2, message: "could not find '<path to missing included gitconfig file>' to stat: No such file or directory" }
  • Error { code: -3, klass: 4, message: "reference 'refs/remotes/origin/main' not found" }
  • Error { code: -3, klass: 0, message: "an unknown git error occurred" }

See e.g. failure on Windows at commit f56262c: https://github.com/martinvonz/jj/runs/3678330357

`jj close` (and some others) sometimes crashes on first attempt with Git backend

jj prune, like most commands, first commit the working copy. When using the Git backend, that produces a Git commit with some hash. The next step for jj prune is to prune the commit. That's done by creating a successor commit with a is_pruned flag set. The problem is that both the predecessors field and the is_pruned field are stored outside of the Git commit and the timestamps are typically the same as well (it happens in much less than a second), so the resulting Git commit remains the same. The Git backend then fails the write (it doesn't allow two Git commits with different non-Git metadata).

I've known about this bug for a long time, but I figured it can be useful to track it. I'm working on removing support for evolution. The bug should be resolved by that work.

cannot source autocompletions in zsh

Expected Behavior

Auto-completions are sourced into the shell.

Actual Behavior

And error message appears and auto-completions are not sourced.

Steps to Reproduce the Problem

Here are different attempts and their results:

~ > source <(jj debug completion --zsh)

_arguments:comparguments:325: can only be called from completion function

~ > source (jj debug completion --zsh)

zsh: unknown file attribute: j

~ > source $(jj debug completion --zsh)

source: no such file or directory: #compdef

~ > source jj debug completion --zsh

/Users/me/.cargo/bin/jj:2: parse error near `)'

~ > jj debug completion --zsh | source

source: not enough arguments

Specifications

  • Version: latest git
  • Platform: zsh on macOS on Silicon with rust nightly via rustup via homebrew

Make `jj status` report commits with conflicts

It seems useful to highlight commits with conflicts (or at least the fact that there are such commits) in jj status. We currently don't have that information available cheaply, so part of this would involve adding that information to the commit index.

Add better support for git-like (ref-based) branches

We'll want to have better support for git-like branches at least for interop with git. I've been thinking a lot about branching recently and I plan to add native support for git-like branches to jj. By "native support", I mean that they can be used regardless of backend.

Related work: Breezy (Bazaar)

I think that among docs/related_work.md Breezy (previously known as Bazaar) should also be mentioned, as it is also both a distinct VCS with its own native storage backend(s), and a backend to the .git storage format, with several interesting features (according to Mark Shuttleworth its unique selling point is accurate history of file renames, for example).

https://www.breezy-vcs.org/
http://bazaar.canonical.com/en/

I think that it is rather more interesting than Mercurial, in particular because its latest native storage layer is much more reasonable, in part because of having a .git storage backend, in part because of keeping well a history of renames (it is file+patch oriented rather than content oriented like git).

Remove nixpkgs-mozilla overlay once nightly features aren't used anymore

Currently the project doesn't build on Rust stable, this means the Nix derivation requires a Rust overlay which supplies the nightly version.

The code which requires the nightly features could be changed, or the nightly features could be stabilized, in which case the nixpkgs overlay should probably be removed such that the Rust compiler from nixpkgs is used instead.

At the time of writing, these nightly features are used:

See also: #66 (comment)

Give better error message on invalid config

I don't know if this is related, but setting the diff_editor under [ui] (in my case to "vimdiff") as instructed in the tutorial doesn't seem to work:

$ jj split -r 3dac3f00b3ad
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: invalid TOML value, did you mean to use a quoted string? at line 4 column 15 in ../.jjconfig', src/main.rs:23:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
$ RUST_BACKTRACE=full jj split -r 3dac3f00b3ad
thread 'main' panicked at 'failed to run diff editor: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/diff_edit.rs:143:10
stack backtrace:
   0:     0x7fe018879fbc - std::backtrace_rs::backtrace::libunwind::trace::he080dbb637fa4641
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x7fe018879fbc - std::backtrace_rs::backtrace::trace_unsynchronized::h44a0cce058c40994
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x7fe018879fbc - std::sys_common::backtrace::_print_fmt::hc4aa1034724314cb
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/sys_common/backtrace.rs:66:5
   3:     0x7fe018879fbc - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h2b790f8be1985180
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/sys_common/backtrace.rs:45:22
   4:     0x7fe0188a4dec - core::fmt::write::h84736921f2ac5f8d
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/core/src/fmt/mod.rs:1190:17
   5:     0x7fe018873a58 - std::io::Write::write_fmt::hfe23991a8d7fa4a7
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/io/mod.rs:1657:15
   6:     0x7fe01887c1e7 - std::sys_common::backtrace::_print::h67116a2d44eae1b1
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/sys_common/backtrace.rs:48:5
   7:     0x7fe01887c1e7 - std::sys_common::backtrace::print::h994f9a0072a4b217
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/sys_common/backtrace.rs:35:9
   8:     0x7fe01887c1e7 - std::panicking::default_hook::{{closure}}::h8f96a84dcab30cf8
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:295:22
   9:     0x7fe01887beaf - std::panicking::default_hook::hb573e2c3be78272d
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:314:9
  10:     0x7fe01887c94a - std::panicking::rust_panic_with_hook::h76b4576d8ac3b270
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:698:17
  11:     0x7fe01887c637 - std::panicking::begin_panic_handler::{{closure}}::h966318ad4399ecd3
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:588:13
  12:     0x7fe01887a464 - std::sys_common::backtrace::__rust_end_short_backtrace::h64a1117353180ced
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/sys_common/backtrace.rs:138:18
  13:     0x7fe01887c339 - rust_begin_unwind
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:584:5
  14:     0x7fe0182cb213 - core::panicking::panic_fmt::h1e67b42cef1db7f9
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/core/src/panicking.rs:143:14
  15:     0x7fe0182cb303 - core::result::unwrap_failed::h1b1ad46cede6e9f5
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/core/src/result.rs:1749:5
  16:     0x7fe01834275c - jujutsu::diff_edit::edit_diff::h11f5f947fdd89247
  17:     0x7fe018306340 - jujutsu::commands::cmd_split::hbe0ab831be98217b
  18:     0x7fe0182cd006 - jujutsu::commands::dispatch::h215fb838a384e92c
  19:     0x7fe0182cddc1 - jj::main::h124478dc1575244a
  20:     0x7fe0182cded3 - std::sys_common::backtrace::__rust_begin_short_backtrace::hec8c8455cb2b9a37
  21:     0x7fe0182cdec9 - std::rt::lang_start::{{closure}}::h11f6c49c99dcd502
  22:     0x7fe0188796a1 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h9d346f7455a6c7fd
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/core/src/ops/function.rs:259:13
  23:     0x7fe0188796a1 - std::panicking::try::do_call::h8ec1a9b8203a1bbc
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:492:40
  24:     0x7fe0188796a1 - std::panicking::try::h695a82b534df1aab
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:456:19
  25:     0x7fe0188796a1 - std::panic::catch_unwind::h6743ebe0ff045bfe
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panic.rs:137:14
  26:     0x7fe0188796a1 - std::rt::lang_start_internal::{{closure}}::h6e3fc46ec5fb4576
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/rt.rs:128:48
  27:     0x7fe0188796a1 - std::panicking::try::do_call::h5c849f12890c52cc
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:492:40
  28:     0x7fe0188796a1 - std::panicking::try::h2c36151dbc2fb3e1
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panicking.rs:456:19
  29:     0x7fe0188796a1 - std::panic::catch_unwind::h5cca8e7db56bc46a
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/panic.rs:137:14
  30:     0x7fe0188796a1 - std::rt::lang_start_internal::h0e034746b466501e
                               at /rustc/75d9a0ae210dcd078b3985e3550b59064e6603bc/library/std/src/rt.rs:128:20
  31:     0x7fe0182cdf02 - main
  32:     0x7fe017b06d0a - __libc_start_main
  33:     0x7fe0182cba4a - _start
  34:                0x0 - <unknown>
$ cat ~/.jjconfig
[user]
name = [REDACTED]
email = [REDACTED]
diff-editor = "vimdiff"

Originally posted by @EyeCon in #18 (comment)

```jj log``` Failed to insert entry: invalid name for a tree entry

Expected Behavior

Log is displayed correctly.

Actual Behavior

jj crashes

xxx@think ~/prj [1]> jj git clone [email protected]:simonw/museums.git museums
Fetching into new repo in "/home/xxx/prj/museums"
Working copy now at: b0941e40a8f0 
xxx@think ~/prj> cd museums/
xxx@think ~/p/museums (main)> jj log
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -1, klass: 14, message: "failed to insert entry: invalid name for a tree entry - .git" }', lib/src/git_store.rs:310:18
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Steps to Reproduce the Problem

  1. Install jj from git following the tutorial's steps)
  2. git clone [email protected]:simonw/museums.git museums
  3. cd museums
  4. jj log

Specifications

  • Version: 0.2.0
  • Platform: Linux x86

Speed up .gitignores

The current support for .gitignore files is a hack that relies on git2::Repository::status_should_ignore(). It's unnecessarily slow to call that for every file in target/ when the .gitignore file contains /target/ -- we should be able to look at the directory and skip all of it.

We may want to fix this by parsing .gitignore files ourselves.

Possible race in git notes when using git backend

Let's say there are two concurrent processes that add commits. They will both try to update the refs/notes/jj/commits (and possibly refs/notes/jj/conflicts) git notes ref when using the git backend. We already retry when that happens, but that's not enough on file systems with poor locking. Perhaps we should record the notes refs and their target in the view object and then update the underlying git repo when resolving conflicts.

Let user resolve repo-level conflicts

We currently resolve repo-level conflicts (such as divergent updates of git refs) arbitrarily. We should instead have the user resolve them. I think it would sense to present them in jj status and have a command for resolving them.

Make it easier to refer to change ids

I suspect I would usually want to refer to change ids instead of commit ids if it was easy to do that. That might reduce the amount of copying from jj log output. Perhaps we should make =abc123 or something like that resolve to any non-obsolete commits with change id abc123. Part of such support would be to accept unique prefixes just like we do for commit ids. (We probably also want to index change ids, but that can come later.)

`jj undo` can result in failing evolution state

The evolution state currently expects all predecessors of a commit to be visible in the repo. That's clearly not a good assumption, especially given that a user should be able to receive a commit from another repo without getting all the predecessors. That can't happen yet because we don't support exchange yet (other than using Git's protocol, which doesn't include our metadata), but predecessor commits can become hidden when using e.g. jj undo of an earlier operation (not the most recent operation).

I've known about this bug for a long time, but I figured it can be useful to track it. I'm working on removing support for evolution. The bug should be resolved by that work.

Consider splitting up the `Store` into `ReadonlyStore` and `MutableStore`

I've very happy with how the separation between ReadonlyRepo and MutableRepo turned out. I think it makes sense to continue that idea by also splitting up Store into ReadonlyStore and MutableStore. The same separation would have to be done in the backends. The idea is that when you load a ReadonlyRepo, it comes with a ReadonlyStore, which in turn has a ReadonlyBackend (Git or native backend). You can't make any writes to the store without starting a transaction. Creating a transaction creates a MutableRepo (as is already the case). That would have a MutableStore, which in turn has a MutableBackend.

Advantages:

  • All writes within a transaction are grouped, which means they can
    go to a single packfile or similar. That means there's no need to have
    loose objects. No special treatment is needed for e.g. fetch and
    fast-import like git does. I suspect it would also make e.g. large
    rebase operations much faster.

  • When you have a ReadonlyRepo pointing to a ReadonlyStore and a
    ReadonlyBackend, the backend can be made more efficient by not
    checking for changes on disk.

  • Objects added within a transaction can go to a temporary file and
    then be discarded if the transaction is discarded (assuming they've
    been written to a place where other processes/threads can't see
    them).

To be clear, the goal (right now anyway) is not to make backend writes transactional. In particular, I don't aim for isolation or atomicity.

worktree equivalent

Does this currently have a git worktree equivalent? Or can it be used with git worktrees somehow?

Add support for `jj diff` to emit unified diffs

The diff format produced by jj diff is supposed to be more human readable, but it makes it harder to collaborate with copy/pasted patch files etc when that becomes an efficient way to share with others. It's also slower to digest for me, as I've got 20 years invested in reading unidiffs natively and colors aren't a great visual cue for me.

(I'd kind of like to do this work, but figured I should track it in a bug anyway.)

jj status does not honor .git/info/exclude

Expected Behavior

jj would honor the existing .git/info/exclude in addition to .gitignore, to allow easier coexistence with git

Actual Behavior

jj status adds local files even if they are excluded by .git/info/exclude

Steps to Reproduce the Problem

  1. git clone https://github.com/martinvonz/jj.git
  2. cd jj && jj init --git-repo .
  3. jj st
  4. observe it says everything is ok
  5. echo secret-password >> .git/info/exclude
  6. touch secret-password
  7. jj status
  8. observe jj has started to track secret-password

I also tried it with jj git clone and then editing .jj/repo/store/git/info/exclude with the same outcome

The problem this is trying to solve is when one does not wish to make formal edits to the upstream repo's .gitignore but also needs jj to stop adding local log files, editor metadata, etc, on any random jj operation

Specifications

  • Version: 2916cb2
  • Platform: darwin/amd64

Error clonning GIT repo

Expected Behavior

Repository is cloned successful.

Actual Behavior

Application crashes.

Fetching into new repo in "/home/pjamar/prj/l/pusharrow"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Other("note for '34d090b9239bf59911ef5365911d2322ae854e19' exists already; class=Repository (6); code=Exists (-4)")', lib/src/store_wrapper.rs:157:58
stack backtrace:
   0:     0x55ad2c3abadc - std::backtrace_rs::backtrace::libunwind::trace::h788b2853b7016c32
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
   1:     0x55ad2c3abadc - std::backtrace_rs::backtrace::trace_unsynchronized::h3626590e16510efa
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x55ad2c3abadc - std::sys_common::backtrace::_print_fmt::ha76294ed367b5eb6
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/sys_common/backtrace.rs:67:5
   3:     0x55ad2c3abadc - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h4244b134876ede81
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/sys_common/backtrace.rs:46:22
   4:     0x55ad2c3d311c - core::fmt::write::h9a6d9c74526a6c1b
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/core/src/fmt/mod.rs:1150:17
   5:     0x55ad2c3a6815 - std::io::Write::write_fmt::h7f8a2ef72f011ad9
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/io/mod.rs:1667:15
   6:     0x55ad2c3adb00 - std::sys_common::backtrace::_print::h4b3c9553c91f7522
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/sys_common/backtrace.rs:49:5
   7:     0x55ad2c3adb00 - std::sys_common::backtrace::print::h36fb46a493801fb8
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/sys_common/backtrace.rs:36:9
   8:     0x55ad2c3adb00 - std::panicking::default_hook::{{closure}}::hf28f6810f0e04677
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:210:50
   9:     0x55ad2c3ad6bb - std::panicking::default_hook::hadb819fa279f9d7b
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:227:9
  10:     0x55ad2c3ae1b4 - std::panicking::rust_panic_with_hook::h015085c4aa271d26
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:624:17
  11:     0x55ad2c3adc90 - std::panicking::begin_panic_handler::{{closure}}::h15a8a2888dd1ba59
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:521:13
  12:     0x55ad2c3abf84 - std::sys_common::backtrace::__rust_end_short_backtrace::h673e204498e49379
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/sys_common/backtrace.rs:141:18
  13:     0x55ad2c3adbf9 - rust_begin_unwind
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:517:5
  14:     0x55ad2be56e01 - core::panicking::panic_fmt::hcf5f6d96e1dd7099
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/core/src/panicking.rs:101:14
  15:     0x55ad2be56ef3 - core::result::unwrap_failed::he898b02f57993c42
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/core/src/result.rs:1617:5
  16:     0x55ad2bfb09e5 - jujutsu_lib::store_wrapper::StoreWrapper::write_commit::h9b4109d36480039e
  17:     0x55ad2bfa2216 - jujutsu_lib::commit_builder::CommitBuilder::write_to_repo::h3d4a0ec6ef15a7ee
  18:     0x55ad2bfca9d6 - jujutsu_lib::repo::MutableRepo::check_out::h9dfbc2734f8d444a
  19:     0x55ad2bea559f - jujutsu::commands::cmd_git::h0d1a626b077d18bc
  20:     0x55ad2be6983c - jujutsu::commands::dispatch::h02e220f6b48def76
  21:     0x55ad2be5fdbd - jj::main::h34cd1dbad16e65e9
  22:     0x55ad2be5f193 - std::sys_common::backtrace::__rust_begin_short_backtrace::h829bc614a367e7e5
  23:     0x55ad2be6aa89 - std::rt::lang_start::{{closure}}::h2077ed056203f4bb
  24:     0x55ad2c3ae7ba - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h61c8e7c7ad965d8f
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/core/src/ops/function.rs:259:13
  25:     0x55ad2c3ae7ba - std::panicking::try::do_call::ha62fd0271612a1de
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:403:40
  26:     0x55ad2c3ae7ba - std::panicking::try::hedc869fcd25323d8
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:367:19
  27:     0x55ad2c3ae7ba - std::panic::catch_unwind::h19fc164e1562e43f
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panic.rs:129:14
  28:     0x55ad2c3ae7ba - std::rt::lang_start_internal::{{closure}}::hb7a70d47e691e1da
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/rt.rs:45:48
  29:     0x55ad2c3ae7ba - std::panicking::try::do_call::h7af85a6c8d4e17cd
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:403:40
  30:     0x55ad2c3ae7ba - std::panicking::try::h2006fd79c11839e7
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panicking.rs:367:19
  31:     0x55ad2c3ae7ba - std::panic::catch_unwind::h554c0031cfe57735
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/panic.rs:129:14
  32:     0x55ad2c3ae7ba - std::rt::lang_start_internal::h0a872604597b44c0
                               at /rustc/29ef6cf1637aa8317f8911f93f14e18d404c1b0e/library/std/src/rt.rs:45:20
  33:     0x55ad2be5fe42 - main
  34:     0x7fc7ab8060b3 - __libc_start_main
  35:     0x55ad2be575de - _start
  36:                0x0 - <unknown>

Steps to Reproduce the Problem

  1. jj git clone ssh://[email protected]:10022/pjamar/pusharrow.git pusharrow

Specifications

  • Version: Jujutsu 0.2.0
  • Platform: Linux/x86

Edit: Added full backtrace

Add a `jj interdiff` command

It should be very easy to implement a command that shows the diff between two commits after rebasing the first command to the second commit's parent(s). This would be useful as part of jj obslog -p/--diff output (that command doesn't accept such a flag yet). (Mercurial's hg obslog -p currently gives up when a commit has been rebased.)

git: SSH config not respected

Expected Behaviour

jj git clone should respect the SSH config (~/.ssh/config).

Actual Behaviour

The SSH config is not respected, which may be problematic in some cases. In this case, ProxyCommand is to communicate with a private Git server.

Steps to Reproduce the Problem

  1. Use an SSH environment which requires additional configuration via ~/.ssh/config to work.
  2. Observe jj git clone hang.

Specifications

  • Version: 0.2.0.r917.2916cb2-1
  • Platform: Linux x86_64

Musl binary for Linux

Expected Behavior

My machine at work doesn't allow any own install.
Can you provide a musl binary>
Many thanks

Actual Behavior

Steps to Reproduce the Problem

Specifications

  • Version:
  • Platform:

Add support for sparse checkouts

I bet this is a lot easier to do than it is in Git and Mercurial thanks to almost everything being done without updating the working copy (including conflicts in paths outside the sparse config).

Make it easier to untrack unwanted files

If you add a file to the repo and it doesn't match the .gitignore, it will currently be automatically tracked. I think that feature has worked pretty well. However, we need to make it easier to untrack the file if you don't want it to be tracked. You currently have to move it out of the working copy, run some command to refresh the working copy, add the file to the .gitignores, then move the file back.

Experiment with word-level merging

I don't know if word-level merging will too often resolve merges incorrectly, but I want to experiment with it. It should be easy to test on existing git repos (like git.git, which has lots of merge commits).

MacOS 12.1 installation fail

Expected Behavior

You follow installation instructions and it should be installed without any errors.

Actual Behavior

I was following installation instructions, but I had several errors.

These fixed the problem:

brew install pkg-config
brew install openssl
export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@3/lib/pkgconfig"

I guess openssl was not needed, but setting PKG_CONFIG_PATH is required

Steps to Reproduce the Problem

  1. Install rustup
  2. rustup install nightly
  3. cargo +nightly install --git https://github.com/martinvonz/jj.git

Specifications

  • Version: 0.2
  • Platform: MacOS 12.1 on Apple Silicon

Support for HTTP Proxy

Expected Behavior

jj git clone uses HTTP proxy according to the http_proxy and https_proxy environment variables.

Actual Behavior

Failure to clone behind proxy.

Error: Fetch failed: Error { code: -1, klass: 2, message: "failed to connect to github.com: Connection timed out" }

Steps to Reproduce the Problem

  1. jj git clone https://github.com/martinvonz/jj.git jj-jj

Specifications

  • Version: fdb861b
  • Platform: Ubuntu 20.04

I know most people and yourself probably don't have proxies, so I'll probably be the one to work on this if I get the time. ๐Ÿ˜„

[Discussion] Stacked Conflicts Representation

You probably have thought about this. I was trying to compare the current conflict representation (two lists, (adds, removes)) with a conservative recursive struct (a tree of (local, other, base)).

To simplify the problem, only file modifications are considered, no deletions.

Consider these recursive structs:

(local: (local: A, other: B, base: C), other: D, base: E)
(local: (local: A, other: D, base: C), other: B, base: E)
(local: (local: A, other: B, base: E), other: D, base: C)

They map to a same flat list representation (IIUC):

(adds: [A, B, D], removes: [C, E])

Apparently some information (ex. relations between merge base and local/other) is lost in this representation but does it matter? To reason about it, here is a question I tried to answer:

  • Suppose doing 3-way merges using one of the recursive structs is conflict-free. Is there an algorithm that takes (adds: [A, B, D], removes: [C, E]) and produces a similar conflict-free merge result?

I couldn't come up with such an algorithm easily. I wonder if that indicates a recursive representation is more practical. It seems there are other benefits, too, such as easier to integrate with existing merge tools and easier to store resolve progress.

Add support for .gitattributes

We'll probably want to support at least the eol attribute. I noticed while using jj in a working copy shared with git that some files appeared modified because they had LF in the commit and CRLF in the working copy.

Consider moving extra metadata from git notes to other storage

The git backend gets really slow after many commits have been created. Profiling has shown that the problem is git notes. One problem is that libgit2 doesn't do sharding. Manually editing a note from the command line using git notes helps, but it's still very slow. We should consider moving the extra metadata to some other storage, perhaps a custom format.

Another option might be for the git backend to simply cache the notes tree. I don't know how much that would help.

One advantage of the current storage in git notes is that it lets us exchange the data using regular git commands.

Add support for symlinks on Windows

We currently don't support symlinks on Windows (in fact, the project doesn't even build on Windows because of that). The advice I got from [email protected] and former hg contributor "bmp" was (please correct me if I'm wrong):

  • Prior to Windows 10: No symlink support
  • Windows 10 without dev mode: No symlink support
  • Windows 10 dev mode: use FFI to call CreateSymbolicLink
  • Don't use the symlink creates, because it creates "junctions", which is not what we want.

Rust's standard library has std::os::windows::fs::symlink_file and std::os::windows::fs::symlink_dir, which both seem to call CreateSymbolicLinkW, only with different flags. Perhaps we can always use the symlink_file version? It's still unclear to me what the effect would be if a "file symbolic link" points to a target that's actually a directory.

crashes if you rename the clone

Expected Behavior

no crash

Actual Behavior

jj commands all fail with this error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', lib/src/git_backend.rs:95:87

With RUST_BACKTRACE=1:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', lib/src/git_backend.rs:95:87
stack backtrace:
   0: rust_begin_unwind
             at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/panicking.rs:142:14
   2: core::result::unwrap_failed
             at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/result.rs:1749:5
   3: jujutsu_lib::git_backend::GitBackend::load
   4: jujutsu_lib::store::Store::load_store
   5: jujutsu_lib::repo::RepoLoader::init
   6: jujutsu_lib::workspace::Workspace::load
   7: jujutsu::commands::CommandHelper::workspace_helper
   8: jujutsu::commands::cmd_status
   9: jujutsu::commands::dispatch
  10: jj::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

with RUST_BACKTRACE=full:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', lib/src/git_backend.rs:95:87
stack backtrace:
   0:     0x55e0d0f2f2bc - std::backtrace_rs::backtrace::libunwind::trace::hede7dd98ee70976c
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x55e0d0f2f2bc - std::backtrace_rs::backtrace::trace_unsynchronized::hbe38aeb3ff19fa80
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x55e0d0f2f2bc - std::sys_common::backtrace::_print_fmt::h8d729be0339480ac
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/sys_common/backtrace.rs:66:5
   3:     0x55e0d0f2f2bc - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h44d89a7c637ba906
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/sys_common/backtrace.rs:45:22
   4:     0x55e0d0f58dcc - core::fmt::write::haccb55fe49c41c09
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/fmt/mod.rs:1190:17
   5:     0x55e0d0f28b08 - std::io::Write::write_fmt::h50fec3265e31260a
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/io/mod.rs:1657:15
   6:     0x55e0d0f314f7 - std::sys_common::backtrace::_print::h5147f75d54ad7c1f
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/sys_common/backtrace.rs:48:5
   7:     0x55e0d0f314f7 - std::sys_common::backtrace::print::hc83faab68ce2b380
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/sys_common/backtrace.rs:35:9
   8:     0x55e0d0f314f7 - std::panicking::default_hook::{{closure}}::ha61fc22abb98b6b0
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:295:22
   9:     0x55e0d0f311af - std::panicking::default_hook::h89b0e33dd598a21f
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:314:9
  10:     0x55e0d0f31c4b - std::panicking::rust_panic_with_hook::h7e9579ddfea6f147
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:698:17
  11:     0x55e0d0f31937 - std::panicking::begin_panic_handler::{{closure}}::h1e78bb9730f8cca8
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:588:13
  12:     0x55e0d0f2f784 - std::sys_common::backtrace::__rust_end_short_backtrace::h3c102b80f36ee941
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/sys_common/backtrace.rs:138:18
  13:     0x55e0d0f31649 - rust_begin_unwind
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:584:5
  14:     0x55e0d0989e63 - core::panicking::panic_fmt::hd296f17a12340ce5
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/panicking.rs:142:14
  15:     0x55e0d0989f53 - core::result::unwrap_failed::hdc2a9475cf94f36c
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/result.rs:1749:5
  16:     0x55e0d0a6bab3 - jujutsu_lib::git_backend::GitBackend::load::h8e00b520cb2414d6
  17:     0x55e0d0a550a5 - jujutsu_lib::store::Store::load_store::hd78181dba576da40
  18:     0x55e0d0aceb3c - jujutsu_lib::repo::RepoLoader::init::hd62d9b61aa18d3fe
  19:     0x55e0d0a8cb6f - jujutsu_lib::workspace::Workspace::load::h48d2ebfe0b508579
  20:     0x55e0d0995aea - jujutsu::commands::CommandHelper::workspace_helper::h0ee8ceb4aacc4b23
  21:     0x55e0d09b6dba - jujutsu::commands::cmd_status::hc1dcdccdc68451e6
  22:     0x55e0d098b8a8 - jujutsu::commands::dispatch::hf5768c8e6ca2007b
  23:     0x55e0d098cbd4 - jj::main::h9fc62cf2aaf605c0
  24:     0x55e0d098f603 - std::sys_common::backtrace::__rust_begin_short_backtrace::h7ef9afa5a98051d7
  25:     0x55e0d098d039 - std::rt::lang_start::{{closure}}::h79f91634bb8322dc
  26:     0x55e0d0f2e971 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hd05d8982c002a1a9
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/core/src/ops/function.rs:259:13
  27:     0x55e0d0f2e971 - std::panicking::try::do_call::ha2de91ec45a309aa
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:492:40
  28:     0x55e0d0f2e971 - std::panicking::try::hf5d233d56c71d201
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:456:19
  29:     0x55e0d0f2e971 - std::panic::catch_unwind::h10747b5e8afc13e6
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panic.rs:137:14
  30:     0x55e0d0f2e971 - std::rt::lang_start_internal::{{closure}}::hcfc4e0221f952948
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/rt.rs:128:48
  31:     0x55e0d0f2e971 - std::panicking::try::do_call::h1bb4ffc2cf7b3c03
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:492:40
  32:     0x55e0d0f2e971 - std::panicking::try::h73c86487a3602c03
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panicking.rs:456:19
  33:     0x55e0d0f2e971 - std::panic::catch_unwind::h81db875d526be813
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/panic.rs:137:14
  34:     0x55e0d0f2e971 - std::rt::lang_start_internal::hc35357b91ce50efe
                               at /rustc/03a8cc7df1d65554a4d40825b0490c93ac0f0236/library/std/src/rt.rs:128:20
  35:     0x55e0d098cf62 - main
  36:     0x7f051dbbeb25 - __libc_start_main
  37:     0x55e0d098a69e - _start
  38:                0x0 - <unknown>

Steps to Reproduce the Problem

Here's what I did:

  1. copy an existing git clone: cp -ar foo foo-test
  2. cd foo-test
  3. jj init --git-repo=.
  4. cd ..
  5. mv foo-test foo-jj-test
  6. cd foo-jj-test
  7. jj status #crash happens here
  8. cd ..
  9. mv foo-jj-test foo-test
  10. cd foo-test
  11. jj status #commands work again

Specifications

  • Version: 0.2.0
  • Platform: archlinux

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.