GithubHelp home page GithubHelp logo

gitbutlerapp / gitbutler Goto Github PK

View Code? Open in Web Editor NEW
10.3K 39.0 421.0 27.41 MB

The GitButler version control client, backed by Git, powered by Tauri/Rust/Svelte

Home Page: https://gitbutler.com

License: Other

JavaScript 0.15% Rust 28.10% HTML 0.01% CSS 0.76% Svelte 9.84% TypeScript 60.93% Shell 0.21%
git github tauri

gitbutler's Introduction

GitButler

Git branch management tool, built from the ground up for modern workflows
gitbutler.com »

Download for macOS (Apple Silicon | Intel) · Linux (AppImage | deb) · Windows (msi)

(Unstable Nightly releases can be found here)


gitbutler_client

CI BADGE TWEET DISCORD INSTA YOUTUBE

GitButler is a git client that lets you work on multiple branches at the same time. It allows you to quickly organize file changes into separate branches while still having them applied to your working directory. You can then push branches individually to your remote, or directly create pull requests.

In a nutshell, it's a more flexible version of git add -p and git rebase -i, allowing you to efficiently multitask across branches.

How Does It Work?

GitButler keeps track of uncommitted changes in a layer on top of Git. Changes to files or parts of files can be grouped into what we call virtual branches. Whenever you are happy with the contents of a virtual branch, you can push it to a remote. GitButler makes sure that the state of other virtual branches is kept separate.

How Do GB's Virtual Branches Differ From Git Branches?

The branches that we know and love in Git are separate universes, and switching between them is a full context switch. GitButler allows you to work with multiple branches in parallel in the same working directory. This effectively means having the content of multiple branches available at the same time.

GitButler is aware of changes before they are committed. This allows it to keep a record of which virtual branch each individual diff belongs to. Effectively, this means that you can separate out individual branches with their content at any time to push them to a remote or to unapply them from your working directory.

And finally, while in Git it is preferable that you create your desired branch ahead of time, using GitButler you can move changes between virtual branches at any point during development.

Why GitButler?

We love Git. Our own @schacon has even published the Pro Git book. At the same time, Git's user interface hasn't been fundamentally changed for 15 years. While it was written for Linux kernel devs sending patches to each other over mailing lists, most developers today have different workflows and needs.

Instead of trying to fit the semantics of the Git CLI into a graphical interface, we are starting with the developer workflow and mapping it back to Git.

Tech

GitButler is a Tauri-based application. Its UI is written in Svelte using TypeScript and its backend is written in Rust.

Main Features

  • Virtual Branches
    • Organize work on multiple branches simultaneously, rather than constantly switching branches
    • Automatically create new branches when needed
  • Easy Commit Management
    • Undo, Amend and Squash commits by dragging and dropping
  • GitHub Integration
    • Authenticate to GitHub to open Pull Requests, list branches and statuses and more
  • Easy SSH Key Management
    • GitButler can generate an SSH key to upload to GitHub automatically
  • AI Tooling
    • Automatically write commit messages based on your work in progress
    • Automatically create descriptive branch names
  • Commit Signing
    • Easy commit signing with our generated SSH key

Example Uses

Fixing a Bug While Working on a Feature

Say that while developing a feature, you encounter a bug that you wish to fix. It's often desirable that you ship the fix as a separate contribution (Pull request).

Using Git you can stash your changes and switch to another branch, where you can commit, and push your fix.

With GitButler you simply assign your fix to a separate virtual branch, which you can individually push (or directly create a PR). An additional benefit is that you can retain the fix in your working directory while waiting for CI and/or code review.

Trying Someone Else's Branch Together With My Work in Progress

Say you want to test a branch from someone else for the purpose of code review.

Using Git trying out someone else's branch is a full context switch away from your own work. With GitButler you can apply and unapply (add / remove) any remote branch directly into your working directory.

Documentation

You can find our end user documentation at: https://docs.gitbutler.com

Bugs and Feature Requests

If you have a bug or feature request, feel free to open an issue, or join our Discord server.

AI Commit Message Generation

Commit message generation is an opt-in feature. You can enable it while adding your repository for the first time or later in the project settings.

Currently, GitButler uses OpenAI's API for diff summarization, which means that if enabled, code diffs would be sent to OpenAI's servers.

Our goal is to make this feature more modular such that in the future you can modify the prompt as well as plug a different LLM endpoints (including local ones).

Contributing

So you want to help out? Please check out the CONTRIBUTING.md document.

If you want to skip right to getting the code to actually compile, take a look at the DEVELOPMENT.md file.

Want to show your support? Add a GitButler badge to your project's README:

[![GitButler](https://img.shields.io/badge/GitButler-%23B9F4F2?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAzOSAyOCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI1LjIxNDUgMTIuMTk5N0wyLjg3MTA3IDEuMzg5MTJDMS41NDI5NSAwLjc0NjUzMiAwIDEuNzE0MDYgMCAzLjE4OTQ3VjI0LjgxMDVDMCAyNi4yODU5IDEuNTQyOTUgMjcuMjUzNSAyLjg3MTA3IDI2LjYxMDlMMjUuMjE0NSAxNS44MDAzQzI2LjcxOTcgMTUuMDcyMSAyNi43MTk3IDEyLjkyNzkgMjUuMjE0NSAxMi4xOTk3WiIgZmlsbD0iYmxhY2siLz4KPHBhdGggZD0iTTEzLjc4NTUgMTIuMTk5N0wzNi4xMjg5IDEuMzg5MTJDMzcuNDU3MSAwLjc0NjUzMiAzOSAxLjcxNDA2IDM5IDMuMTg5NDdWMjQuODEwNUMzOSAyNi4yODU5IDM3LjQ1NzEgMjcuMjUzNSAzNi4xMjg5IDI2LjYxMDlMMTMuNzg1NSAxNS44MDAzQzEyLjI4MDMgMTUuMDcyMSAxMi4yODAzIDEyLjkyNzkgMTMuNzg1NSAxMi4xOTk3WiIgZmlsbD0idXJsKCNwYWludDBfcmFkaWFsXzMxMF8xMjkpIi8%2BCjxkZWZzPgo8cmFkaWFsR3JhZGllbnQgaWQ9InBhaW50MF9yYWRpYWxfMzEwXzEyOSIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgxNi41NzAxIDE0KSBzY2FsZSgxOS44NjQxIDE5LjgzODMpIj4KPHN0b3Agb2Zmc2V0PSIwLjMwMTA1NiIgc3RvcC1vcGFjaXR5PSIwIi8%2BCjxzdG9wIG9mZnNldD0iMSIvPgo8L3JhZGlhbEdyYWRpZW50Pgo8L2RlZnM%2BCjwvc3ZnPgo%3D
)](https://gitbutler.com/)

BADGE

gitbutler's People

Contributors

03juan avatar abhishekthorat avatar alabhyajindal avatar askielboe avatar byron avatar caleb-t-owens avatar codesmith-emmy avatar daniils avatar dependabot[bot] avatar extrawurst avatar eyalch avatar gitbutler-client avatar idonahue avatar kjy5 avatar krlvi avatar kronik907 avatar mayfieldiv avatar meesayen avatar michaelowendyer avatar mtsgrd avatar namanlp avatar ngalaiko avatar olenayefymenko avatar pavellaptev avatar pranav2612000 avatar qix- avatar robinsmith-source avatar schacon avatar tobyjwebb avatar vidluther 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

gitbutler's Issues

Client User Onboarding

The first time you open the app, we should detect that you are a new user and run you through an onboarding process. This would be to connect to your GitButler account or sign up for a new one, point it at your first project, describe what we're doing a little, ask for permissions to collect data, etc. All of these can be changed in User/Account settings later, but we need a first project and some instructions.

  • Login to our server (magic link / Auth0) or sign up
  • Or choose to use offline only
  • Connect a first project
    • Give the project a human readable name
    • Identify a master branch
  • Walkthrough features if user is new

View hook failure logs

If a commit hook fails, it's difficult to see why. Maybe we can show the output on a failure?

GitButler errors if repository doesn't have any commits

If you point GitButler to a repository without any commits, you'll get the following error:
Error: Something went wrong

It would be great if the error message was specific or, ideally, GitButler would allow you to create the first commit.

I'm running version 0.9.17 (20240118.182445).

Steps to reproduce

  1. Run git init in a new directory
  2. Add a new project in GitButler pointing to the directory

Multithreading in diff calculation

wrt https://discord.com/channels/1060193121130000425/1073202153163857920/1203599833236119552

I changed a 39MB ts file (generated obviously) and the entire UI stopped working.

  • no new changes showed up
  • after restart a never ending spinner
  • 1 cpu core at 100%
  • nothing in the logs

I had to recover by stashing from old school git and applying the changes back in a regular branch. Deleting the integration branch and restarting.

Outside observation: the diff calculation is single threaded and running on an M3 efficiency core. Making this multithreaded would significantly speed this up (at least on my machine)

Add to Homebrew

Hi,

I really love your app and appreciate the hard work your putting on it. I would really appreciate if you added it to the homebrew package manager for macOS. This would help us developers keep our packages up to date easier.

Much appreciated, Kara

Missing package creation field 'Maintainer' for Deb packages

Reported via email:

% apt-get install -y git-butler_0.9.21_amd64.deb
# or dpkg -i git-butler_0.9.21_amd64.deb

% dpkg --configure -a

dpkg: warning: parsing file '/var/lib/dpkg/status' near line 15910 package 'git-butler':
missing 'Maintainer' field

% cat /var/lib/dpkg/status

Package: git-butler
Status: install ok installed
Priority: optional
Installed-Size: 244177
Architecture: amd64
Version: 0.9.21
Depends: libayatana-appindicator3-1, libwebkit2gtk-4.0-37, libgtk-3-0
Description: (none)
(none)

Error message displayed in Gitbutler due to syntax error in `projects.json`

Hey. It just happened again that my projects.json had an syntax error. Closed yesterday night my laptop with Gitbutler running. Today I opened the laptop and found that Gitbutler app displayed an error message. (forgot to take a screen). Checked the projects.json and at the end it had something like:

...
    "project_data_last_fetch": {
      "error": {
        "timestamp": {
          "secs_since_epoch": 1706828585,
          "nanos_since_epoch": 216435000
        },
        "error": "failed to fetch"
      }
    }
  }
]iled to fetch"
      }
    }
  }

via: @PalMartin

https://discord.com/channels/1060193121130000425/1073202153163857920/1202882531196665936

Github Action for tauri app builds

Use GitHub to automatically build the Tauri app on all supported platforms. It would be nice to let the web app know (when we have one) when this occurs so we can promote builds to the auto-updater.

Crash on pop-os 22.04 / git-butler 0.10

Crash

Running git-butler leads to a crash on pop-os 22.04 (basically ubuntu 22.04):

 git-butler

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
[1]    16464 IOT instruction (core dumped)  git-butler

Installation Log/Audit Trail

Installed deb of 0.10

❯ dpkg -l git-butler
dpkg-query: warning: parsing file '/var/lib/dpkg/status' near line 8828 package 'git-butler':
 missing 'Maintainer' field
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ STDIN
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ Desired=Unknown/Install/Remove/Purge/Hold
   2   │ | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
   3   │ |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
   4   │ ||/ Name           Version      Architecture Description
   5   │ +++-==============-============-============-=================================
   6   │ ii  git-butler     0.10.0       amd64        (none)
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ dpkg -L git-butler
dpkg-query: warning: parsing file '/var/lib/dpkg/status' near line 8828 package 'git-butler':
 missing 'Maintainer' field
/usr
/usr/share
/usr/share/applications
/usr/share/applications/git-butler.desktop
/usr/share/icons
/usr/share/icons/hicolor
/usr/share/icons/hicolor/256x256@2
/usr/share/icons/hicolor/256x256@2/apps
/usr/share/icons/hicolor/256x256@2/apps/git-butler.png
/usr/share/icons/hicolor/128x128
/usr/share/icons/hicolor/128x128/apps
/usr/share/icons/hicolor/128x128/apps/git-butler.png
/usr/share/icons/hicolor/32x32
/usr/share/icons/hicolor/32x32/apps
/usr/share/icons/hicolor/32x32/apps/git-butler.png
/usr/bin
/usr/bin/git-butler

Windows - Cannot add any git directory

Steps to reproduce:

  1. Start via pnpm tauri dev
  2. Press Add New Project
  3. Wait for the prompt
  4. Using windows file picker select a folder w/ a valid git repo.

ipc->add_project: {"path":"C:\Users\username\Documents\websites\git"} Error: Something went wrong
at UserError.fromError (ipc.ts:30:10)
at ipc.ts:81:33
at async ProjectService.add (projects.ts:79:19)
at async HTMLButtonElement.onNewProject (Welcome.svelte:17:23) {code: 'errors.unknown', message: 'Something went wrong'}

I even tried creating a new git repo from scratch in a different directory and disk, but the issue still happened.

image

(Potentially KDE Plasma Wayland specific): Taskbar icon doesn't seem to show hide Windows correctly.

Relevant System Config Information
Version: AppImage 0.10.4
Distribution: Arch Linux
DE: Plasma 5.27.10 (Wayland)
Kernel: 6.6.16

Steps to reproduce
Start the app, close the Window (or hide via the system tray).
Click "Show GitButler"
Nothing happens but the system tray gets stuck on "Hide GitButler"

I can test XOrg on Arch later (and Wayland with the current kernel), but I'll need to use my personal machine as my work machine needs fractional scaling from Wayland to display certain things correctly.

Client Dashboard

The client should have a dashboard where you can see all your projects and a unified timeline of all your projects workspaces. You can visualize how you switch around your projects, change your current focused project, etc. Perhaps we can auto-switch you into a project if we see you editing it (beware of log changes, etc, though gitignore should mostly handle that).

  • can see all projects
  • can add new projects to watch
  • can switch into a project context
  • can see a unified timeline
  • can access user / account settings

branch search input disappears when no branch match

When I am searching for a branch, the search input disappears if the search does not match any branch. The search input should remain visible so the user can edit his search

Screen.Recording.2024-02-06.at.14.21.26.mov

hidpi screen = scalling not right

hy i want to give this app a try i am on linux and i use X11 with a hidpi scalling and xftpi is set to Xft.dpi: 133 in .Xresources to set up the scaling so my other apps respects that so no apps look too small but gitbuttler's diff panes scalling is very small to be comfortable to me is there any way to control the scalling factor etc

screeenshot

image

📦 FlatPak package

While the AppImage is nice, it also feels weird a bit and automatic app updates aren't possible.

Hence I wanted to install GitButler natively but I needed an RPM since I'm running Fedora.
I thought that I could just convert the .deb package with Alien (sudo alien -r git-butler_0.9.14_amd64.deb) but I'm getting this error when trying to install it:

image

So I guess a native installation won't work.

Hence I'd like to see a Flatpak to be available. It works on every Linux distribution the same while also allowing to update the apps centralised.

User action concurrency

wrt https://discord.com/channels/1060193121130000425/1073202153163857920/1203605030637412432

When i'm doing actions in the UI, everything happens sequentially, even tasks that should be independent of each other.

  • Clicking create pull request -> spinner, click new branch because i want to keep working on the next thing, nothing happens until the PR is created (which is also kind of slow btw)
  • Same thing happens when dragging 1 file, and then dragging another

The experience is best described as 'doing one thing at the same time with some sort of single process queue of actions'.

Can't open submodule

On macOS, I cannot open my repository that is a submodule (https://github.com/hermit-os/kernel inside https://github.com/hermit-os/hermit-rs).

For reproduction:

git clone --recursive [email protected]:hermit-os/hermit-rs.git

Then try to open hermit-rs/kernel in GitButler.

[...]
2024-02-05T13:07:48.611165Z ERROR add_project: gitbutler-app/src/projects/commands.rs:75: failed to add project error=failed to open repository

Caused by:
    path not found: /Users/mkroening/Downloads/hermit-rs/kernel/.git/objects path="/Users/mkroening/Downloads/hermit-rs/kernel"
[...]

The user interface only has a small toast notification, “Something went wrong.”

Move line-based changes around (instead of hunk-based changes)

Currently, git-butler works with hunks.

In a significant number of times, hunks are too coarse grained for me. Therefore, I like the line-based workings of git gui.

image

(Artificial example to show the context menu)

I would love if git-butler could support line-based drag'n'drop, too.

By that I mean:

Variant 1:

  1. User drags a single line inside a hunk to another virtual branch
  2. git-butler removes that change from the origin branch and places it to the target (virtual) branch

Variant 2:

  1. User marks an area of text inside a hunk. That area is typically 2 to n lines long.
  2. User drag'n'drops this area to another virtual branch
  3. git-butler removes change touched by the area from the origin branch and places it to the target (virtual) branch

Can't back out of adding new project

On macOS, after clicking “Add new project” and selecting a directory, you are prompted to select a target branch. There is a “Back” button next to “Let's go!”, but it does not work. Even after restarting the app, I can't leave the screen.

Resetting the app with rm -rf ~/Library/Application\ Support/com.gitbutler.app works.

Git authentication fails

Hey folks,

the git authentication is failing for me through the Gitbutler client. It is however working fine through the git CLI and various IDEs (Intellij and VSCode for example).

My setup:

  • GitHub auth via SSH keys
  • The SSH identity is stored in my OpenSSH auth agent (ssh-add -l)
  • The identity to use for GitHub is defined within my SSH config (cat ~/.ssh/config)

Within Gitbutler, I tried the Auto Detect mode, as well as Use existing SSH key (without passphrase).

Error shown within Gitbutler:

image

Basic Local Recording

The client needs to record everything happening in the working directory. We decided this would be via git commits of the state of the working tree (tracked and untracked files) along with metadata of the crdt deltas from the last tree to this one.

Each commit will happen when there is at least 5 minutes of no changes, or every hour at maximum. We will also record metadata about the session.

The tree structure linked to by each commit will look like this:

- wd/
   - README.md
   - lib/
     - config.rb
   [etc]
- session/
  - meta/
    - session-start (timestamp)
    - session-last (timestamp)
    - branch (branch name)
    - commit (last commit sha) 
  - deltas/
    - README.md (crdt data, with git blob SHA as base)
    - lib/
      - config.rb (crdt data)  

This should be done by a Rust watcher process per project, spawned and managed by the client.

Basic Timeline UI

The client needs a way to view the data that it is recording. This should be presented as a timeline to the user and the user should have some tooling to inspect and compare data at any point in the timeline.

  • can view any file at any moment in history from the time the client first began watching a project
  • can filter for a path or specific file name
  • can revert a file to a previous state
  • can diff a file to what is currently on disk
  • some sort of visualization of the history
  • some sort of indication that recording is happening continuously

Git hooks are not executed

For me git pre-commit hooks aren't executed.
Judging from #2551 it seems like they should be, just without being able to view the output?

Remote Sync - Client

The client should be able to upload the changes they are recording to an offline service. This should by default be our servers, but if the user does not want to use our service, they can provide their own endpoint.

  • figure out the push target through a configuration setting
  • automatically trigger a push when a commit happens
  • push both the gitbutler head and all other heads (so we can cross reference) to us, but only the gb head to another
  • timeout if there is no network connection, try again on the next commit
  • if us, pull auth tokens from the server, rotate occasionally (maybe daily)

Hard to understand changeset

CleanShot 2024-02-04 at 10 35 32@2x

the ..(uiBuilder line switched places with the CommonLayerModule which vscode and Tower show in a way that is understandable

CleanShot 2024-02-04 at 10 36 50@2x
CleanShot 2024-02-04 at 10 37 26@2x

What is weird is that the second part of the changeset, where CommonLayerModule is added on line 73, has does not show uiBuilder on line 72.

This either needs to be 1 changeset like the tower screenshot or in part 2 line 72 should be the uiBuilder line

Error while opening Project

When I tried to open a currently working git repository. I got error like this

image

Then I cloned this repo and Tried to see what's causing Issue.
In there I found that, One file don't have a read permission in that directory.
That's causing issue.

When i add that is in .gitignore, It's working fine.


2024-02-12T18:13:14.208850Z ERROR add_project: gitbutler-app/src/projects/commands.rs:75: failed to add project error=failed to open repository

Caused by:
    0: failed to run initial flush
    1: failed to build working directory tree
    2: failed to build wd index
    3: failed to add working directory path .../liveStreaming.csv
    4: failed open - '/Users/..../liveStreaming.csv' is locked: Permission denied; class=Os (2) path="/Users/..."

SCR-20240212-ullo-2.

Floating Git Butler icon

There is a random floating icon of GitButler on the top-left of the screen covering the Apple logo and hence the menu

image

🦊 GitLab support

It would be nice also being able to create Merge Requests from GitButler on GitLab the same way it supports creating Pull Requests on GitHub. 😉

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.