Cursor Cloud Agents are now in Graphite. Create, review, and ship without leaving your PR.
Read more
The new standard for developer infrastructure
Graphite CLI
Streamline Git commands and seamlessly stack pull requests from your terminal.
Pull request inbox
Stay on top of every PR and review request in one unified inbox.
Graphite Chat
Get immediate, actionable feedback on every pull request with Graphite Chat.
Merge Queue
Eliminate merge conflicts and keep your main branch green—whether you're a team of 10 or 10,000.
Insights and reports
Accelerate your team with powerful, real-time developer metrics.
Start a stack
Create the first branch in your stack with gt create.
Keep stacking
Run gt create again to stack another branch on top of your previous changes without waiting for them to merge into main.
Visualize your stack
Get a bird's eye view of your stack with gt log.
Publish your stack
Create or update PRs for every branch in your stack with gt submit.
Respond to feedback
Update changes across your stack with gt modify. Graphite handles all of the recursive rebasing for you.
Ship, sync, repeat
Automatically sync your local stack with remote changes, and clean up stale branches with gt sync.
Every change in one place
Stay on top of your team's pull requests from one dashboard. See reviews, CI status, stack info, and everything else you need to know about your PRs.
Fully customizable
Customize each inbox section to match your workflow. Filter PRs based on author, CI status, reviews, labels, and much, much more.
As fast as you are
Keyboard shortcuts, at-a-glance statuses, and real-time GitHub sync help you stay up-to-date and take action on things that need your attention.
Pull requests the way they should be
File diffs, version history, comments, and CI in one intuitive interface. Code review has never been this enjoyable.
42+export const updateBaseBranchIfNecessary = async ({
43+ pr,
44+ newMergeBase,
45+ actor,
46+ serverContext,
47+}: {
48+ pr: PrToRebase;
49+ newMergeBase: string;
50+ actor: GithubCachedActorWithHost;
51+ serverContext: TServerContext;
52+}) => {
53+ const { owner, repo, number } = pr;
54
55+ const skipUpdateBaseBranchIfUnchanged =
56+ await serverContext.clients.statsig.checkOrgBasedFlagDeprecated({
57+ configName: "skip_update_base_branch_if_unchanged",
58+ orgGithubLogins: [owner],
59+ splog: serverContext.splog,
60+ });
61
62+ if (skipUpdateBaseBranchIfUnchanged) {
63+ const freshPr =
64+ await serverContext.clients.githubCache.pullRequests.getFreshPrAndCache({
65+ githubClient,
66+ owner,
67+ repo,
68+ number,
69+ source: "REBASE_UPDATE_BASE_BRANCH",
70+ config: {
71+ await: true,
72+ },
73+ });
74
75+ if (freshPr && freshPr.baseRef.name === newMergeBase) {
76+ return;
77+ }
78+ }
79
80+ const sleepSeconds = await determineSleepTime({ owner, serverContext });
81+ await sleep({ seconds: sleepSeconds });
82
83+ serverContext.splog.verbose({
84+ message: `Updating PR base branch after rebase`,
85+ tags: { pr, newMergeBase },
86+ });
87
88+ await updatePrBase({
89+ owner,
90+ repo,
91+ prNumber: pr.number,
92+ base: newMergeBase,
93+ githubClient,
94+ context: serverContext,
95+ });
96+};
97
98+export async function rebasePullRequest({
99+ pr,
100+ actor,
101+ newMergeBase,
102+ stackJobId,
103+ gitClient,
104+ serverContext,
105+}: {
106+ pr: PrToRebase;
107+ actor: GithubCachedActorWithHost;
108+ newMergeBase: string;
109+ stackJobId: string;
110+ gitClient: GitClient;
111+ serverContext: TServerContext;
112+}): Promise<RebaseResult> {
113+ const rebaseStartTime = DateTime.now();
114+ const rebaseResult = await gitClient.rebaseUnmergedRange({
115+ headBranch: pr.headBranch,
116+ trunkBranch: newMergeBase,
117+ });
118
119+ const durationMs = startTime
120+ .diff(DateTime.now())
121+ .as("milliseconds");
122
123+ serverContext.splog.verbose({
124+ message: `Rebase completed in ${rebaseDurationMs}ms`,
125+ tags: {
126+ rebaseDurationMs,
127+ pr,
128+ newMergeBase,
129+ },
130+ });
131
132+ if (rebaseResult !== "SUCCESS") {
133+ serverContext.splog.warn({
134+ message: `Failed to rebase ${pr.owner}/${pr.repo}#${pr.number}`,
135+ tags: {
136+ pr,
137+ newMergeBase,
138+ rebaseResult,
139+ },
140+ });
141+ return { result: rebaseResult };
142+ }
Graphite Chat automatically scans opened PRs for bugs, logical errors, and other technical pitfalls so reviewers can focus on the big picture.
Graphite Chat ensures that every piece of feedback makes sense in the context of your codebase.
Define and enforce custom patterns with AI prompts and regex.
Beyond vanity
Visualize and track data-driven metrics that are proven to enhance developer productivity.
Transparency
Graphite Insights empowers every member of your team with data—regardless of their role.
A historical record
Graphite Insights measures developer trends over time, allowing you to identify and fix bottlenecks in your engineering workflow.
Keep changes flowing
Graphite Merge Queue puts your merge process on autopilot, keeping your engineers unblocked.
Merge from anywhere
Merge PRs from Graphite, GitHub, or even your terminal.
Save money and CI time
Powerful CI optimizations skip redundant tests, saving you time and money.