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


76

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

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

使用SVN,它将是

svn up -r800

达到修订版800,以及

svn up

与存储库同步。

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

git reset <hash>

这似乎使我到达那里。但是后来我尝试

git pull

但这抱怨冲突。

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

我在考虑SVN,所以请毫不犹豫地向我指出一些不错的教程。请注意,我已经检查了http://git.or.cz/course/svn.htmlhttp://www.youtube.com/watch?v=8dhZ9BXQgc4

谢谢,恩德拉。


1
旁注:我习惯git pull完全避免。取而代之的是,我在bash中使用git fetch --allalias to gu,并一直gitk打开,查看所有分支-请参阅View-> edit-> Check all 4复选框。然后,我根据需要使用git resetgist stash+移动git co
OndraŽižka2012年

Answers:


71

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

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

仅使用git pushgit pull与仓库同步。可以将其想像成使用rsync或任何备份解决方案,使两个地方的内容完全相同。就像您连接外部备份硬盘一样,然后使其中的内容与主硬盘中的内容相同。这就是git pull和的用法git push

如果您只是想回溯历史,请使用git checkout。使用查看修订版本ID git history。如果您使用的是Linux,请使用gitk来查看修订树。在Windows中,乌龟git可以使用修订图显示它。

要返回最新版本,请使用git checkout master。在执行任何命令之前,请务必使自己做好git status。此命令将显示您需要了解的有关当前回购条件的所有信息,以及需要采取哪些措施才能使其正确执行。之前做git pullgit push,它的更好,以确保git status结果是包含文本working directory clean

如果您需要将文件还原到以前的版本,可以使用git merge。在对文件进行处理之前,请先使用进行测试git diff。例如:git diff rev1:rev2 filename。它将打印出两个修订版之间的所有差异。rev1中的更改​​将由rev2中的更改代替。因此,要进行还原,rev2将比rev1更早。当您与差异结果满足,这样做有git merge,只需更换diffmerge所有其他参数保持不变。

我希望这可以帮助你。主要的关键是要看到您的工作目录是您的仓库。了解这一点将帮助您充分利用git的全部功能。祝好运。


39

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

git checkout具有提交ID而不是分支名称的分支将使您从任何命名分支移至所谓的独立头

如果使用,git reset则它将分支本身移回旧状态,从而孤立了较新的提交(可能不是您想要的)。


什么是checkout真的呢?通过在当前状态和给定提交状态之间反向应用提交补丁,它是否将文件更改为给定提交状态?
OndraŽižka,2010年

我发现git resetgit reset origin。我不会进行任何提交,因此,只要可以轻松恢复(只要使用一个命令),就是否松开最近的提交都没有关系。
OndraŽižka,2010年

1
git checkout不会使更改永久生效。为此,请使用git merge。查看我的答案。
Donny Kurnia 2010年

1
检出将索引/缓存/暂存区重置为给定提交所指定的树,然后更新工作树以匹配缓存。它不需要重新申请任何补丁;它只是在给定提交时使用树。(它还具有错误检查功能,如果您将其传递为分支名称,则会更新已签出的分支。)
CB Bailey 2010年

30

其他答案是有益的,但我认为这最接近OP的要求:

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

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

# checkout next (newer) commit
git_next() {
    BRANCH=`git show-ref | grep $(git show-ref -s -- HEAD) | sed 's|.*/\(.*\)|\1|' | grep -v HEAD | sort | uniq`
    HASH=`git rev-parse $BRANCH`
    PREV=`git rev-list --topo-order HEAD..$HASH | tail -1`
    git checkout $PREV
}

用法:

$ 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让恢复正常。


完成这些操作后,看看git别名可能是值得的。
rethab

我喜欢这个答案,它正在工作一分钟,但是现在当我运行git_next时,我得到了usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color=when] [--context[=num]] [--directories=action] [--label] [--line-buffered] [--null] [pattern] [file ...]
Squirrl 18-10-30

11

Try git reflog,它列出了您要在提交之间进行切换的提交和签出,甚至包括在签出到上一个提交时丢失的提交。

然后,您可以尝试git checkout <hash of a commit>切换到该提交。

希望这可以帮助!


7

要签出文件的其他版本,请使用

git checkout rev -- filename

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

使用git loggitk看看审查的版本就看你想要的文件的版本。

要使此版本的文件成为永久文件,您需要提交文件: git add filename; git commit filename

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

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


这样做的时候要小心。我的同事执行了此命令,以尝试从我的分支机构进行更改,从而耗费了大约一周的时间,并通过此操作将其推送到存储库中……
karina

只要您的同事没有执行push -f,您就可以始终还原其提交并恢复丢失的工作。如果您有权访问他推送的仓库,甚至可以通过git reflog恢复推送。另外,如果您仍然有分支机构,则可以恢复。但是,是的,您必须要小心。
Jamey Hicks
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.