{"payload":{"header_redesign_enabled":false,"results":[{"body":"Ordinarily, Git garbage collects all orphaned commits and deletes them after a period of time, under the assumption that you're not using them anymore, and they're just taking up space. In the branchless workflow, this behavior is suppressed. Orphaned commits are not allowed to be garbage collected by Git unless they are also hidden (see \"Visibility\"). That is to say, Git won't garbage collect commits as long as they're still visible in the smartlog, even if they don't have a branch attached to them. To emphasize, git-branchless only ever causes fewer commits to be garbage-collected than normal. The practical impact is that old hidden commits may be garbage-collected by Git after some time. You won't be able to access them, even with git undo .","filename":"Advanced-topic:-garbage-collection.md","format":"markdown","hl_body":"Ordinarily, Git garbage collects all orphaned commits and deletes them after a period of time, under the assumption that you're not using them anymore, and they're just taking up space. In the ...","hl_title":"Advanced topic: garbage collection","id":"ee0e573e47ca54469663bf05a2fa38c0523f61f1","path":"Advanced-topic:-garbage-collection.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Advanced topic: garbage collection","updated_at":"2021-09-27T17:17:31.000-07:00"},{"body":"The git-branchless project is not the future of version control. Instead, the goal is to 1) provide a natural half-step to Jujutsu , which accomplishes most git-branchless workflows in a more principled way; and to 2) serve as a test-bed for new workflows that Jujutsu might want to adopt in the future. The design goals of the git-branchless project are as follows: Support onboarding : Make it easy for new users to adopt git-branchless. Prefer to allow users to adopt tools incrementally, without having to opt into a complete workflow change. Example: git undo can be used while ignoring the rest of the suite. Documentation is a first-class goal, but tools should naturally prompt users to do the right thing. Example: when you abandon a commit, a warning appears to suggest that you run git restack . Decrease complexity : Git is overly complex. Prefer to reduce complexity rather than manage complexity. Remove concepts from Git which don't work well. Example: the staging area is incidental complexity. It would be better to support partial commits via different means. Unify concepts where possible. Example: Git stashes can be represented as regular Git commits, if the tooling provides enough support. Increase velocity : Users should be able to carry out common workflow operations quickly and enjoy fast feedback loops. Commits and branches should be easier to make and throw away (hence the name \"git-branchless\"). It should be possible to experiment without losing work. Example: git undo makes commit graph operations safer to use, because they can be easily rolled back. Perform well : git-branchless must scale to monorepo-sized repositories, without suffering performance degradation. Commands should complete in milliseconds. Operations which take longer than that (such as querying git status ) need to be considered carefully before including them as part of a core workflow.","filename":"Design-goals.md","format":"markdown","hl_body":"The git-branchless project is not the future of version control. Instead, the goal is to 1) provide a natural half-step to Jujutsu , which accomplishes most git-branchless workflows in a more principled ...","hl_title":"Design goals","id":"90403fafdb455bbd284e236d7750ec7d022430c7","path":"Design-goals.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Design goals","updated_at":"2022-11-02T12:46:08.000-07:00"},{"body":"Welcome to the git-branchless wiki! See Installation to install git-branchless . Then see Tutorial for an overview of how to use the various commands, and Concepts for more details about the underlying concepts. You can also check Related tools to learn about other tools which you might find useful. If you have a technical question not covered by the documentation, or if you'd like to learn more about workflows and patterns with git-branchless , start a discussion !","filename":"Home.md","format":"markdown","hl_body":"Welcome to the git-branchless wiki! See Installation to install git-branchless . Then see Tutorial for an overview of how to use the various commands, and Concepts for more details about the underlying ...","hl_title":"Home","id":"f4dc7bd067bdf556a65152a4559a5d4287ed47c1","path":"Home.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Home","updated_at":"2022-04-12T21:18:50.000-07:00"},{"body":"If you're interested in contributing to git-branchless , I'm happy to set up a call with you to walk you through the project. I reside in the Pacific timezone (UTC-8). Start a discussion with your idea and tag me, or send me an email at me@waleedkhan.name .","filename":"Onboarding.md","format":"markdown","hl_body":"If you're interested in contributing to git-branchless , I'm happy to set up a call with you to walk you through the project. I reside in the Pacific timezone (UTC-8). Start a discussion with your ...","hl_title":"Onboarding","id":"7c224a8d36dc722ff77f5220ac51af72f26400af","path":"Onboarding.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Onboarding","updated_at":"2021-09-17T20:23:55.000-07:00"},{"body":"This is a list of questions on Stack Overflow which are neatly answered by git-branchless. It could be worth referring back to these to address pain points, or updating them as the tooling improves. Git rebase subtree Rebasing a branch including all its children How do I rebase a chain of local git branches? Could update this answer with git sync later. Modify base branch and rebase all children at once","filename":"Stack-Overflow-questions.md","format":"markdown","hl_body":"This is a list of questions on Stack Overflow which are neatly answered by git-branchless. It could be worth referring back to these to address pain points, or updating them as the tooling improves. Git ...","hl_title":"Stack Overflow questions","id":"c69279b43a18088df064b15979a38c6c7f145148","path":"Stack-Overflow-questions.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Stack Overflow questions","updated_at":"2021-10-24T11:14:34.000-07:00"},{"body":"TODO: explain an alternative to stashing commits with git-branchless . If you want to learn more, file an issue and I'll prioritize this documentation :)","filename":"Workflow:-stashing.md","format":"markdown","hl_body":"TODO: explain an alternative to stashing commits with git-branchless . If you want to learn more, file an issue and I'll prioritize this documentation :)","hl_title":"Workflow: stashing","id":"1b4e78da7688aeb5132621fbf1e2506413c02318","path":"Workflow:-stashing.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Workflow: stashing","updated_at":"2021-10-17T17:19:05.000-07:00"},{"body":"For users of Nix git-branchless is also available as a Nix flake. Flakes are only available in Nix 2.4 or newer and require the following experimental features to be set in the nix.conf: experimental-features = nix-command flakes Afterwards the new Nix CLI commands can be used to launch a shell where git-branchless is available using nix shell github:arxanas/git-branchless Users who like to be on the bleeding edge can add git-branchless to their flake inputs and use the included overlay to add git-branchless to their profile. { inputs.git-branchless.url = \"github:arxanas/git-branchless\"; outputs = { self, nixpkgs, git-branchless, ... }: let system = \"x86_64-linux\"; pkgs = import nixpkgs { inherit system; overlays = [ git-branchless.overlays.default ]; }; in { # flake outputs ... # pkgs.git-branchless refers to the GitHub version }; }","filename":"Nix-flake.md","format":"markdown","hl_body":"For users of Nix git-branchless is also available as a Nix flake. Flakes are only available in Nix 2.4 or newer and require the following experimental features to be set in the nix.conf: experimental-features ...","hl_title":"Nix flake","id":"f7fb11ba3c509a1e83bda37d1471fd31f1ab7745","path":"Nix-flake.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Nix flake","updated_at":"2024-06-01T22:09:36.000+02:00"},{"body":"Recipes See Revset recipes for some ideas and examples on how to use revsets. Grammar The latest grammar is in grammar.lalrpop . Names are resolved using the same logic as git rev-parse . Additionally, . is a synonym for HEAD . Built-in functions The following functions are defined: all() : all visible commits . none() : the empty set of commits. union(x, y) : all commits that are in either x or y . intersection(x, y) : all commits that are in both x and y . difference(x, y) : all commits that are in x but not in y . only(x, y) : all commits which are ancestors of x , but not ancestors of y . range(x, y) : all commits which are both descendants of x and ancestors of y . ancestors(x) : all commits which are ancestors of commits in x . A commit is an \"ancestor\" of x if it is x or it is a parent of an ancestor of x . Note that this definition includes x itself in the set of ancestors of x . ancestors.nth(x, n) : the n th generation ancestor of x , following only the first parents. Equivalent to ~n . descendants(x) : all commits which are descendants of commits in x . A commit is a \"descendant\" of x if it is x or it is a child of a descendant of x . Note that this definition includes x itself in the set of descendants of x . parents(x) : all commits which are an immediate parent of a commit in x . parents.nth(x, n) : the n th parent of x . Equivalent to ^n children(x) : all commits which are an immediate child of a commit in x . roots(x) : all commits in x which have no immediate ancestors also in x . heads(x) : all commits in x which have no immediate descendants also in x . merges() : all merge commits. (Available since v0.9.0) main() : the main branch commit. (Available since v0.6.0.) public() : all public commits, which is to say, all commits on the main branch. This is the same as ancestors(main()) . (Available since v0.6.0.) draft() : all draft commits . stack([x]) : all draft commits in the commit stack containing x . Without arguments, refers to the current commit stack (i.e. the one containing HEAD ). branches([text-pattern]) : all commits with branches pointing to them. If a pattern is provided, the result is restricted to commits whose branches match that pattern. (Available since v0.9.0.) message(text-pattern) : all commits whose messages match the specified pattern. paths.changed(text-pattern) : all commits with a changed file path matching the specified pattern. author.name(text-pattern) : all commits whose author name matches the specified pattern. author.email(text-pattern) : all commits whose author email matches the specified pattern. author.date(date-pattern) : all commits whose author date matches the specified pattern. committer.name(text-pattern) : all commits whose committer name matches the specified pattern. committer.email(text-pattern) : all commits whose committer email matches the specified pattern. committer.date(date-pattern) : all commits whose committer date matches the specified pattern. exactly(x, n) : all commits in x , but only if x contains exactly n commits. (Available since v0.5.0.) current(x) : the current version of all commits in x . (Available since v0.6.0.) Commits in x that have been rewritten (for example, by being moved, reworded, amended, restacked, etc) will be resolved to their current version. Commits in x that have not been rewritten will be included as is. tests.passed([test-command-pattern]) : all commits whose most recent test run for the specified test command passed. If no test command is specified, refers to the most-recently-run test command. (Available since v0.7.0.) tests.failed([test-command-pattern]) : all commits whose most recent test run for the specified test command failed. If no test command is specified, refers to the most-recently-run test command. (Available since v0.7.0.) tests.fixable([test-command-pattern]) : all commits whose most recent test run for the specified test command wrote output to the working copy, which could be used with git test fix to apply the changes. If no test command is specified, refers to the most-recently-run test command. (Available since v0.7.0.) Operators The following unary operations are defined: :x : same as ancestors(x) . ::x is also accepted to be familiar for Mercurial users. x: : same as descendants(x) . x:: is also accepted to be familiar for Mercurial users. The following binary operations are defined: + , | , or : same as union . & , and : same as intersection . - : same as difference . Note that foo-bar is parsed as a branch name. To force the binary operation parsing, write foo - bar instead. % : same as only . : : same as range . :: is also accepted to be familiar for Mercurial users. .. : same as only . Patterns Text patterns: foo , substr:foo , substring:foo : matches if the text contains foo anywhere. exact:foo : matches if the entire text content is exactly foo . glob:foo/* : matches if the text content matches the glob pattern foo/* anywhere. regex:foo.* : matches if the text content matches the glob pattern foo.* anywhere. Dates can be either absolute ( 2022-01-01 ) or relative ( 1 month ago ). Date patterns: before:date : matches if the date is before date . after:date : matches if the date is after date . Test command patterns: these are the same as text patterns and match against the full test command as run by git test . In particular, test command aliases are not stored in historical test run data, so test command matching is always performed against the fully-expanded test command. Aliases Aliases may be defined via git config to provide easy access to oft used revset constructs. Parameters are supported, too: $1 will be replaced with the first parameter, $2 with the second, etc. They can be defined from the command line: $ git config --global \\\n branchless.revsets.alias.d \\\n \"draft()\"` Or directly in the git config file: [branchless \"revsets.alias\"]\n grandChildren = children(children($1))\n sole = exactly($1, 1)\n onlyChild = sole(children($1))\n onlyParent = sole(parents($1))\n siblings = children(onlyParent($1)) - $1 Then, they can be used anywhere that git branchless accepts revsets : $ git query 'd()'\n...\n\n$ git reword 'sole(siblings(abc123))'\n...","filename":"Reference:-Revsets.md","format":"markdown","hl_body":"Recipes See Revset recipes for some ideas and examples on how to use revsets. Grammar The latest grammar is in grammar.lalrpop . Names are resolved using the same logic as git rev-parse . Additionally, ...","hl_title":"Reference: Revsets","id":"49ce6221e656b352938299c95e4e79900e6fd310","path":"Reference:-Revsets.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Reference: Revsets","updated_at":"2024-05-26T16:18:32.000-07:00"},{"body":"Crate documentation:","filename":"Architecture.md","format":"markdown","hl_body":"Crate documentation:","hl_title":"Architecture","id":"cec2f3e6f9986e02979109dd3ce97bbe99d63df1","path":"Architecture.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Architecture","updated_at":"2024-05-04T19:45:12.000Z"},{"body":"Printing messages and progress reporting The Effects type is used to manage printing output and displaying progress to the user. It can be used to show the progress of nested tasks, including with spinners or progress meters. It's not safe to call println! or eprintln! directly, because the output may clobber or be clobbered by progress reporting mechanisms. Instead, call one of the following, as appropriate: writeln ! ( effects.get_output_stream ( ) , \"message {}\" , param1, ... ) ; writeln ! ( effects.get_error_stream ( ) , \"message {}\" , param1, ... ) ; as appropriate. Logging For logging, the project uses the tracing library. You can generate logs using macros like tracing::warn! . These macros support structured logging, so you can directly include variables which you want to log, without having to convert them to strings first: // Includes the contents of `buffer` in the log message.\nwarn!(?buffer, \"WriteProgress dropped while buffer was not empty\"); To display logs at runtime, set the RUST_LOG environment variable. For example: $ RUST_LOG=info cargo run smartlog Error-handling Most of the project uses the eyre library for error-handling. The eyre::Result type allows you to use the ? operator with nearly any error type, rather than having to wrap every third-party library Result into a project- or function-specific Result type. Span traces Stack traces are displayed with the help of the color-eyre and tracing-error libraries. Technically, span traces are recorded, not stack traces. These correspond to functions which have been explicitly annotated using the tracing library, such as with #[tracing::instrument] . Other function calls are not included in the span trace. Example span trace When the program exits with error, a span trace will appear: $ cargo run smartlog\n Compiling git-branchless v0.3.4 (/Users/wkhan/workspace/git-branchless)\n Finished dev [unoptimized + debuginfo] target(s) in 5.74s\n Running `target/debug/git-branchless smartlog`\nError:\n 0: Could not find repository main branch\n\nLocation:\n src/git/repo.rs:302 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n 0: branchless::commands::smartlog::smartlog with effects= < Output fancy=true > at src/commands/smartlog.rs:269 The span trace includes branchless::commands::smartlog::smartlog because it is wrapped with #[tracing::instrument] . Also notice that it includes the parameter value effects , along with its Debug representation. Adding functions to the span trace When you want a function to appear in the span trace, you must do one of two things: Wrap the function definition with #[tracing::instrument] . This is best for first-party code: Only the definition needs to be wrapped with #[instrument] . Callers don't have to remember to call wrap_err_with every time they call the function. Parameter values are included in the span trace as well. Call wrap_err_with on a Result to turn it into an eyre::Result . This is best for third-party libraries which don't use eyre::Result , or when additional information needs to be added to an operation. Including parameter values in the span trace By default, #[tracing::instrument] -annotated functions will include all of their parameters in the span trace by getting their Debug representations, which is helpful for debugging. However, parameters should not be included when the Debug representation is very large. A parameter whose type doesn't implement Debug can't be included at all. To skip printing a certain parameter in the span trace: add a skip to tracing::instrument : # [ instrument ( skip ( value ) ) ] fn set_config ( effects : & Effects , config : & mut Config , name : & str , value : impl Into < ConfigValue > , ) - > eyre :: Result < ( ) > { vs. anyhow The project also uses the similar anyhow library in a few cases: When an error needs to be sent between threads. The eyre::ErrReport type is not Send , so we use the anyhow::Error type instead. When interfacing with another library that uses anyhow::Error . vs. Result When specific error values need to be consumed by the rest of the program, rather than reported to the user, the project uses the standard library Result instead (or in addition). If necessary, the thiserror library could also be used to compose these kinds of errors. Compile times To keep compile times down, heed the advice in Fast Rust Builds . In particular, you'll see some examples of reducing monomorphization in the codebase: eyre::ErrContext::wrap_err is called in preference to eyre::ErrContext::wrap_err_with . The latter takes a function as its argument, which is slower to process by the compiler, and slightly increases code size. If the containing function is marked with #[instrument] , then its parameter values will be printed in the span-trace, so they don't need to be duplicated in the wrap_err / wrap_err_with message. Thus, wrap_err_with is only useful when there are other values which should be included in the error message, such as local variables. Functions which take Into < Foo > or AsRef < Foo > immediately defer to a function which is specialized to take Foo / & Foo . This also makes it easier to include the parameter values with #[instrument] , as Into < Foo > / AsRef < Foo > won't be Debug , but Foo often is. The git module The project wraps Git operations into its own git module, rather than use the types from e.g. git2 directly. This is for a few reasons: To be able to swap out the Git implementation. We may use the gitoxide library in the future. We may want to back some operations with the git executable rather than via git2 . We may want to integrate with e.g. Watchman in the future. To improve API correctness. The Oid type is split into MaybeZeroOid and NonZeroOid . The git2 library returns a git2::Error for cases such as an object not being found. Our wrapper detects those cases and instead returns an Option . To improve API performance. The git2 library works with Index es, which scale with the size of the repository, rather than the size of the change to the repository. This makes some operations very slow, such as cherry-picking changes. The project offers alternative implementations which don't use Index es. Types specific to git2 , etc., should not escape the git module. Instead, our own wrapper types should be exposed.","filename":"Coding.md","format":"markdown","hl_body":"Printing messages and progress reporting The Effects type is used to manage printing output and displaying progress to the user. It can be used to show the progress of nested tasks, including with spinners ...","hl_title":"Coding","id":"2b30032c5564ef89842a81552a5d8c46027dbfe8","path":"Coding.md","public":true,"repo":{"repository":{"id":320370787,"name":"git-branchless","owner_id":454057,"owner_login":"arxanas","updated_at":"2024-09-23T18:45:31.523Z","has_issues":true}},"repo_id":320370787,"title":"Coding","updated_at":"2024-05-04T19:45:12.000Z"}],"type":"wikis","page":1,"page_count":4,"elapsed_millis":151,"errors":[],"result_count":37,"facets":[],"protected_org_logins":[],"topics":null,"query_id":"","logged_in":false,"sign_up_path":"/signup?source=code_search_results","sign_in_path":"/login?return_to=https%3A%2F%2Fgithub.com%2Fsearch%3Fq%3Drepo%253Aarxanas%252Fgit-branchless%2B%26type%3Dwikis","metadata":null,"warn_limited_results":false},"title":"Wiki search results"}