Skip to content

Commit ed103f5

Browse files
Copilotalexr00
andcommitted
Fix issue with wrong commit being checked out when local branch exists
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
1 parent 8d7e57c commit ed103f5

2 files changed

Lines changed: 77 additions & 8 deletions

File tree

src/github/pullRequestGitHelper.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,38 @@ export class PullRequestGitHelper {
9191
const remoteName = remote.remoteName;
9292
let branch: Branch;
9393

94+
// Always fetch the remote branch first to ensure we have the latest commits
95+
const trackedBranchName = `refs/remotes/${remoteName}/${branchName}`;
96+
Logger.appendLine(`Fetch tracked branch ${trackedBranchName}`, PullRequestGitHelper.ID);
97+
progress.report({ message: vscode.l10n.t('Fetching branch {0}', branchName) });
98+
await repository.fetch(remoteName, branchName);
99+
const trackedBranch = await repository.getBranch(trackedBranchName);
100+
94101
try {
95102
branch = await repository.getBranch(branchName);
96103
// Make sure we aren't already on this branch
97104
if (repository.state.HEAD?.name === branch.name) {
98105
Logger.appendLine(`Tried to checkout ${branchName}, but branch is already checked out.`, PullRequestGitHelper.ID);
99106
return;
100107
}
108+
109+
// Check if local branch is pointing to the same commit as the remote
110+
if (branch.commit !== trackedBranch.commit) {
111+
Logger.debug(`Local branch ${branchName} commit ${branch.commit} differs from remote commit ${trackedBranch.commit}. Updating local branch.`, PullRequestGitHelper.ID);
112+
progress.report({ message: vscode.l10n.t('Updating branch {0} to match remote', branchName) });
113+
// Delete and recreate the local branch to point to the remote commit
114+
await repository.deleteBranch(branchName, true);
115+
await repository.createBranch(branchName, false, trackedBranch.commit);
116+
// Get the updated branch reference
117+
branch = await repository.getBranch(branchName);
118+
}
119+
101120
Logger.debug(`Checkout ${branchName}`, PullRequestGitHelper.ID);
102121
progress.report({ message: vscode.l10n.t('Checking out {0}', branchName) });
103122
await repository.checkout(branchName);
104123

105124
if (!branch.upstream) {
106125
// this branch is not associated with upstream yet
107-
const trackedBranchName = `refs/remotes/${remoteName}/${branchName}`;
108126
await repository.setBranchUpstream(branchName, trackedBranchName);
109127
}
110128

@@ -114,16 +132,11 @@ export class PullRequestGitHelper {
114132
await repository.pull();
115133
}
116134
} catch (err) {
117-
// there is no local branch with the same name, so we are good to fetch, create and checkout the remote branch.
135+
// there is no local branch with the same name, so we are good to create and checkout the remote branch.
118136
Logger.appendLine(
119-
`Branch ${remoteName}/${branchName} doesn't exist on local disk yet.`,
137+
`Branch ${branchName} doesn't exist on local disk yet. Creating from remote.`,
120138
PullRequestGitHelper.ID,
121139
);
122-
const trackedBranchName = `refs/remotes/${remoteName}/${branchName}`;
123-
Logger.appendLine(`Fetch tracked branch ${trackedBranchName}`, PullRequestGitHelper.ID);
124-
progress.report({ message: vscode.l10n.t('Fetching branch {0}', branchName) });
125-
await repository.fetch(remoteName, branchName);
126-
const trackedBranch = await repository.getBranch(trackedBranchName);
127140
// create branch
128141
progress.report({ message: vscode.l10n.t('Creating and checking out branch {0}', branchName) });
129142
await repository.createBranch(branchName, true, trackedBranch.commit);

src/test/github/pullRequestGitHelper.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,62 @@ describe('PullRequestGitHelper', function () {
4444
sinon.restore();
4545
});
4646

47+
describe('fetchAndCheckout', function () {
48+
it('fetches remote and updates local branch when local branch exists with different commit', async function () {
49+
const url = 'git@github.com:owner/name.git';
50+
const remote = new GitHubRemote('origin', url, new Protocol(url), GitHubServerType.GitHubDotCom);
51+
const gitHubRepository = new MockGitHubRepository(remote, credentialStore, telemetry, sinon);
52+
53+
const prItem = convertRESTPullRequestToRawPullRequest(
54+
new PullRequestBuilder()
55+
.number(100)
56+
.user(u => u.login('me'))
57+
.base(b => {
58+
(b.repo)(r => (<RepositoryBuilder>r).clone_url('git@github.com:owner/name.git'));
59+
})
60+
.head(h => {
61+
h.repo(r => (<RepositoryBuilder>r).clone_url('git@github.com:owner/name.git'));
62+
h.ref('my-branch');
63+
})
64+
.build(),
65+
gitHubRepository,
66+
);
67+
68+
const pullRequest = new PullRequestModel(credentialStore, telemetry, gitHubRepository, remote, prItem);
69+
70+
// Setup: local branch exists with different commit than remote
71+
const localBranch = {
72+
type: RefType.Head,
73+
name: 'my-branch',
74+
commit: 'local-commit-hash',
75+
upstream: undefined,
76+
};
77+
repository.state.refs.push(localBranch);
78+
repository._branches.push(localBranch);
79+
80+
// Setup: remote branch has different commit
81+
const remoteBranch = {
82+
type: RefType.RemoteHead,
83+
name: 'refs/remotes/origin/my-branch',
84+
commit: 'remote-commit-hash',
85+
};
86+
repository.state.refs.push(remoteBranch);
87+
repository._branches.push(remoteBranch);
88+
89+
const remotes = [remote];
90+
91+
// Expect fetch to be called
92+
repository.expectFetch('origin', 'my-branch');
93+
94+
await PullRequestGitHelper.fetchAndCheckout(repository, remotes, pullRequest, { report: () => undefined });
95+
96+
// Verify that the local branch was updated to point to the remote commit
97+
const updatedBranch = repository._branches.find(b => b.name === 'my-branch');
98+
assert.strictEqual(updatedBranch?.commit, 'remote-commit-hash');
99+
assert.strictEqual(repository.state.HEAD?.name, 'my-branch');
100+
});
101+
});
102+
47103
describe('checkoutFromFork', function () {
48104
it('fetches, checks out, and configures a branch from a fork', async function () {
49105
const url = 'git@github.com:owner/name.git';

0 commit comments

Comments
 (0)