Git:如何在提交之间来回移动

发布于 2024-08-19 02:16:09 字数 706 浏览 7 评论 0原文

我有一个关于 Git 的新手问题:

我需要在分支的历史记录中来回移动。 这意味着,我需要将所有文件恢复到某些旧版本中的状态,然后我需要返回到存储库中的最新状态。我不需要承诺。

使用 SVN,将

svn up -r800

达到修订版 800,并

svn up

与存储库同步。

我知道我想要返回的提交的哈希值,所以我尝试了

git reset <hash>

这似乎可以让我到达那里。但后来我尝试了

git pull

,但抱怨冲突。

那么浏览分支历史的正确方法是什么?

我正在考虑 SVN,所以请不要犹豫,给我指点一些不错的教程。请注意,我已经检查了 http://git.or.cz/course/svn.html< /a> 和 http://www.youtube.com/watch?v=8dhZ9BXQgc4

谢谢,昂德拉。

I have a newbie question about Git:

I need to move back and forth in a history of a branch.
That means, I need to get all the files to the state they were in in some old revision, and then I need to get back to the latest state in the repository. I don't need to commit.

With SVN, it would be

svn up -r800

to get to revision 800, and

svn up

to get in sync with the repository.

I know the hash of the commit I want to get back to, so I tried

git reset <hash>

which seems to get me there. But then I tried

git pull

but that complains about conflicts.

So what's the proper way to move through the history of the branch?

I'm thinking in terms of SVN, so don't hezitate to point me to some nice tutorial. Note that I've already checked http://git.or.cz/course/svn.html and http://www.youtube.com/watch?v=8dhZ9BXQgc4 .

Thanks, Ondra.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

美人如玉 2024-08-26 02:16:09

我也是前 svn 用户,现在我的所有项目都使用 git。

使用git时,你应该改变svn中使用的客户端-服务器架构的思维方式。在svn中,每次更改都需要与服务器连接。使用 git,您的存储库位于工作目录中。您不需要为每个存储库操作建立连接。

仅使用 git push 和 git pull 与存储库同步。可以将其视为使用 rsync 或任何备份解决方案来使两个位置具有完全相同的内容。就像你连接外置备份硬盘一样,然后将其中的内容与你的主硬盘中的内容保持一致。这就是 git pull 和 git push 的用法。

如果您只想在历史记录中来回查看,请使用 git checkout 来完成。使用 git log 查看修订 ID。如果您使用的是 Linux,请使用 gitk 查看修订树。在Windows中,tortoise git可以使用修订图来显示它。

要返回到最新版本,请使用 git checkout master 。在执行任何命令之前,请始终让自己执行git status。此命令将显示您需要了解的有关当前回购条件的所有信息,以及您需要采取哪些操作才能使其正确。在执行git pullgit push之前,最好确保git status结果显示working Directory clean

如果您需要将文件恢复到之前的版本,可以使用 git merge 来完成。在对文件执行此操作之前,请先使用 git diff 对其进行测试。例如:git diff rev1:rev2 文件名。它将打印出两个修订版之间的任何差异。 rev1 中的更改将被 rev2 中的更改替换。因此,要进行恢复,rev2 将比 rev1 旧。对 diff 结果感到满意后,使用 git merge 进行操作,只需将 diff 替换为 merge 即可,所有其他参数保持不变。

我希望这对你有帮助。主要的关键是查看您的工作目录是您的存储库。理解这一点将帮助您充分利用 git 的功能。祝你好运。

I'm a former svn user too and now use git for all my projects.

When using git, you should change your way of thinking from the client-server architecture that's used in svn. In svn, every change needs a connection with the server. Using git, your repo is in the working directory. You don't need a connection for every repo action.

Only use git push and git pull to synchronise with the repo. Think of it as using rsync or any backup solution to make two places have exactly the same content. Just like when you connect external backup hard disk, then make the content in it same with the content in your main. That's the usage of git pull and git push.

If you just want to go back and forth in the history, do it using git checkout. See the revision id using git log. If you're using Linux, use gitk to see the revision tree. In Windows, tortoise git can display it using revision graph.

To get back to latest revision, use git checkout master. Before doing any command, always make yourself do git status. This command will display anything you need to know about current repo condition, and what action you need to do to make it right. Before doing git pull and git push, it's better to make sure that the git status result shows working directory clean.

If you need to revert a file to its previous revision, you can do it with git merge. Before doing it to a file, test it first with git diff. Ex: git diff rev1:rev2 filename. It will print out any differences between two revisions. Changes in rev1 will be replaced by the changes in rev2. So to do revert, rev2 will be the older than rev1. After you are satisfied with the diff result, do it with git merge, just replace diff with merge and all other parameters stay the same.

I hope this helps you. The main key is to see that your working dir is your repo. Understanding this will help you use git to it's full capability. Good luck.

烂人 2024-08-26 02:16:09

您可以使用 git checkout 签出任何提交,然后将其与分支名称一起使用以返回到指定分支。

带有提交 ID 而不是分支名称的 git checkout 会将您从任何命名分支转移到所谓的分离头。

如果您使用 git reset ,那么它会将您的分支本身移回旧状态,从而孤立最近的提交,这可能不是您想要的。

You can use git checkout to checkout any commit and then use it with a branch name to go back to a named branch.

git checkout with a commit id and not a branch name moves you off any named branch and on to what is known as a detached head.

If you use git reset then it will move your branch itself back to an old state, orphaning the more recent commits which probably isn't what you want.

月竹挽风 2024-08-26 02:16:09

更新 2024 年 3 月 17 日:修复 @deltacrux + 高级设置

其他答案内容丰富,但我相信这最接近OP想要的:

将这两个函数添加到您的〜/.bashrc中:

# checkout prev (older) revision
git_prev() {
    git checkout HEAD~
}

# checkout next (newer) commit
git_next() {
  branch=$(git branch --contains HEAD | grep -v HEAD | tail -1 | sed 's/^[ *]*//g')
  hash=$(git rev-parse $branch)
  next=$(git rev-list --topo-order HEAD..$hash | tail -1)
  git checkout $next
}

用法:< /strong>

$ git_prev
Previous HEAD position was 7042c8a... Commit message2
HEAD is now at d753ecc... Commit message1

$ git_next
Previous HEAD position was d753ecc... Commit message1
HEAD is now at 7042c8a... Commit message2

注意:这些命令始终输入 分离 HEAD 状态。如果您从当前签出的分支中git_prev然后git_next,您最终将回到最新版本,但您将处于分离的HEAD状态。执行 git checkout BRANCH_NAME 以恢复正常。


高级设置:

这是我个人使用的设置。

  • 将命令缩短为 gp (git_prev) 和 gn (git_next)。
  • git checkout 添加 gc 命令。
  • 添加 gcr 命令以退出分离的 HEAD 状态(git checkout reset)。
  • 将分支名称保存在 .git/_PREV_BRANCH 中,这样就不会有“跳”到包含相同提交的不同分支的风险。
  • gn 上自动退出分离的 HEAD 状态,返回到分支提交(因此您可以 gp + gn 立即回到开始的位置)。
# save branch name (if not detached)
# this allows gcr to exit detached HEAD state and gn to better determine the next commit
git_save_branch() {
  branch=$(git rev-parse --abbrev-ref HEAD)
  if [ "$branch" != "HEAD" ]; then
    echo "$branch" >.git/_PREV_BRANCH
  fi
}

# loads the previously saved branch name, or guesses what branch we are in if detached
git_load_branch() {
  if [ -f .git/_PREV_BRANCH ]; then
    cat .git/_PREV_BRANCH
  else
    git branch --contains HEAD | grep -v HEAD | tail -1 | sed 's/^[ *]*//g'
  fi
}

# checkout
gc() {
  git_save_branch
  git checkout "$@"
}

# reset to last saved branch
gcr() {
  branch=$(git_load_branch)
  if [ -n "$branch" ]; then
    git checkout "$branch"
  else
    echo "No saved branch to reset to"
    return 1
  fi
}

# checkout prev (older) commit
gp() {
  git_save_branch
  git checkout HEAD~
}

# checkout next (newer) commit
gn() {
  branch=$(git_load_branch)
  hash=$(git rev-parse $branch)

  # stop if we are already on the branch, i.e. there are no newer commits
  head_hash=$(git rev-parse HEAD)
  if [ $hash = $head_hash ]; then
    echo "On branch $branch"
    return 0
  fi

  next=$(git rev-list --topo-order HEAD..$hash | tail -1)

  # if the next commit is the branch commit, checkout the branch to exit detached HEAD state
  if [ $next = $hash ]; then
    git checkout $branch
  # otherwise, checkout the next commit
  else
    git checkout $next
  fi
}

UPDATE 2024-03-17: Fix from @deltacrux + Advanced Setup

The other answers are informative, but I believe this is closest to what the OP wants:

Add these two functions to your ~/.bashrc:

# checkout prev (older) revision
git_prev() {
    git checkout HEAD~
}

# checkout next (newer) commit
git_next() {
  branch=$(git branch --contains HEAD | grep -v HEAD | tail -1 | sed 's/^[ *]*//g')
  hash=$(git rev-parse $branch)
  next=$(git rev-list --topo-order HEAD..$hash | tail -1)
  git checkout $next
}

Usage:

$ git_prev
Previous HEAD position was 7042c8a... Commit message2
HEAD is now at d753ecc... Commit message1

$ git_next
Previous HEAD position was d753ecc... Commit message1
HEAD is now at 7042c8a... Commit message2

Note: These commands always enter detached HEAD state. If you git_prev then git_next from a currently checked out branch, you will end up back at the latest revision but you will be in detached HEAD state. Do git checkout BRANCH_NAME to get back to normal.


Advanced Setup:

Here's the setup I use personally.

  • Shortens commands to gp (git_prev) and gn (git_next).
  • Adds gc command for git checkout.
  • Adds gcr command to exit detached HEAD state (git checkout reset).
  • Saves the branch name in .git/_PREV_BRANCH so that there is no risk of "hopping" to a different branch that contains the same commit.
  • Automatically exits detached HEAD state on gn back to the branch commit (so you can gp + gn to get right back where you started).
# save branch name (if not detached)
# this allows gcr to exit detached HEAD state and gn to better determine the next commit
git_save_branch() {
  branch=$(git rev-parse --abbrev-ref HEAD)
  if [ "$branch" != "HEAD" ]; then
    echo "$branch" >.git/_PREV_BRANCH
  fi
}

# loads the previously saved branch name, or guesses what branch we are in if detached
git_load_branch() {
  if [ -f .git/_PREV_BRANCH ]; then
    cat .git/_PREV_BRANCH
  else
    git branch --contains HEAD | grep -v HEAD | tail -1 | sed 's/^[ *]*//g'
  fi
}

# checkout
gc() {
  git_save_branch
  git checkout "$@"
}

# reset to last saved branch
gcr() {
  branch=$(git_load_branch)
  if [ -n "$branch" ]; then
    git checkout "$branch"
  else
    echo "No saved branch to reset to"
    return 1
  fi
}

# checkout prev (older) commit
gp() {
  git_save_branch
  git checkout HEAD~
}

# checkout next (newer) commit
gn() {
  branch=$(git_load_branch)
  hash=$(git rev-parse $branch)

  # stop if we are already on the branch, i.e. there are no newer commits
  head_hash=$(git rev-parse HEAD)
  if [ $hash = $head_hash ]; then
    echo "On branch $branch"
    return 0
  fi

  next=$(git rev-list --topo-order HEAD..$hash | tail -1)

  # if the next commit is the branch commit, checkout the branch to exit detached HEAD state
  if [ $next = $hash ]; then
    git checkout $branch
  # otherwise, checkout the next commit
  else
    git checkout $next
  fi
}
§普罗旺斯的薰衣草 2024-08-26 02:16:09

尝试git reflog,它列出了您在提交之间切换时所做的提交和签出,甚至是签出到上一个提交时丢失的提交。

然后您可以尝试 git checkout <提交的哈希> 切换到该提交。

希望这有帮助!

Try git reflog, this lists commits and checkouts you have done to switch between the commits, even the commits you have lost when checkout to a previous commit.

Then you can try git checkout <hash of a commit> to switch to that commit.

Hope this helps!

空心空情空意 2024-08-26 02:16:09

要签出文件的不同版本,请使用

git checkout rev -- filename

其中 rev 可以是提交的 ID、分支的名称、标签的名称或相对版本。

使用 git log、gitk 来检查版本以查看您想要的文件版本。

要使该版本的文件永久存在,您需要提交该文件: git add filename; git commit filename

我不建议使用 git pull 检查版本,因为它会进行合并——可能会修改您当前的状态。

在这种情况下,您不需要使用 git reset ,除非您决定不提交 git add 一个文件。

To checkout a different version of a file, use

git checkout rev -- filename

Where rev can be the ID of a commit, the name of a branch, the name of a tag, or a relative version.

Use git log, gitk to look examine versions to see which version of the file you want.

To make this version of the file permanent, you need to commit the file: git add filename; git commit filename

I would not recommend git pull to examine versions because it does a merge -- potentially modifying your current state.

You do not need to use git reset in this case, unless you git add a file you decide not to commit.

◇流星雨 2024-08-26 02:16:09

根据您在 git 历史记录中来回移动的原因,您可能会考虑仅查看历史记录。

我发现这篇文章试图找出如何最好地查看提交历史记录和更改,以便我可以熟悉一个项目。我最终使用了 git log -p --oneline 。

-p 标志显示每次提交之间的差异。请参阅此处了解更多信息。

Depending on your reason for moving back and forth through the git history, you might consider just viewing the history.

I found this post trying to figure out how to best view the commit history and changes so I could familiarize myself with a project. I ended up using git log -p --oneline.

The -p flag shows the differences between each commit. See more here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文