#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
namespace fastIO {
bool IOerror = 0;
inline char nc() {
  static char buf[100000], *p1 = buf + 100000, *pend = buf + 100000;
  if (p1 == pend) {
    p1 = buf;
    pend = buf + fread(buf, 1, 100000, stdin);
    if (pend == p1) {
      IOerror = 1;
      return -1;
    }
  }
  return *p1++;
}
inline bool blank(char ch) {
  return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
template <class T>
inline bool read(T &x) {
  bool sign = 0;
  char ch = nc();
  x = 0;
  for (; blank(ch); ch = nc())
    ;
  if (IOerror) return false;
  if (ch == '-') sign = 1, ch = nc();
  for (; ch >= '0' && ch <= '9'; ch = nc()) x = x * 10 + ch - '0';
  if (sign) x = -x;
  return true;
}
inline bool read(double &x) {
  bool sign = 0;
  char ch = nc();
  x = 0;
  for (; blank(ch); ch = nc())
    ;
  if (IOerror) return false;
  if (ch == '-') sign = 1, ch = nc();
  for (; ch >= '0' && ch <= '9'; ch = nc()) x = x * 10 + ch - '0';
  if (ch == '.') {
    double tmp = 1;
    ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
      tmp /= 10.0, x += tmp * (ch - '0');
  }
  if (sign) x = -x;
  return true;
}
inline bool read(char *s) {
  char ch = nc();
  for (; blank(ch); ch = nc())
    ;
  if (IOerror) return false;
  for (; !blank(ch) && !IOerror; ch = nc()) *s++ = ch;
  *s = 0;
  return true;
}
inline bool read(char &c) {
  for (c = nc(); blank(c); c = nc())
    ;
  if (IOerror) {
    c = -1;
    return false;
  }
  return true;
}
template <class T, class... U>
bool read(T &h, U &...t) {
  return read(h) && read(t...);
}
};  // namespace fastIO
using namespace fastIO;
void DEBUGll(long long *a, int n) {
  for (int i = 0; i <= n; i++) printf("%lld%c", a[i], " \n"[i == n]);
}
void DEBUGint(int *a, int n) {
  for (int i = 0; i <= n; i++) printf("%d%c", a[i], " \n"[i == n]);
}
void freio() {}
const int MAXN = 4e5 + 5;
const int MAXM = MAXN << 1;
const int mod = 10007;
const int INF = 0X3f3f3f3f;
struct LB {
  long long d[100];
  int tot;
  LB() {
    tot = 0;
    memset(d, 0, sizeof(d));
  }
  bool add(long long x) {
    for (int i = 63; ~i; i--) {
      if (x & (1ll << i)) {
        if (d[i])
          x ^= d[i];
        else {
          d[i] = x;
          break;
        }
      }
    }
    return x > 0;
  }
  long long Min1(long long x) {
    long long ans = x;
    for (int i = 63; ~i; i--)
      if ((ans ^ d[i]) < ans) ans ^= d[i];
    return ans;
  }
} lb;
int n, m, q;
map<pair<int, int>, int> mp;
struct node {
  int u, v, w;
  node(int _u = 0, int _v = 0, int _w = 0) { u = _u, v = _v, w = _w; }
};
node E[MAXN];
vector<node> sgt[MAXN << 2];
void insert(int t, int l, int r, int x, int y, node e) {
  if (x <= l && y >= r) {
    sgt[t].emplace_back(e);
    return;
  }
  int mid = (l + r) >> 1;
  if (x <= mid) insert(t << 1, l, mid, x, y, e);
  if (y > mid) insert(t << 1 | 1, mid + 1, r, x, y, e);
}
struct sta {
  int x, y, add;
} st[MAXN];
int top;
int fa[MAXN], f[MAXN], dep[MAXN];
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
int dis(int x) { return fa[x] == x ? 0 : f[x] ^ dis(fa[x]); }
void merge(int x, int y, int w) {
  if (dep[x] > dep[y]) swap(x, y);
  st[++top] = {x, y, dep[x] == dep[y]};
  fa[x] = y, f[x] = w;
  if (dep[x] == dep[y]) dep[y]++;
}
pair<int, int> Q[MAXN];
void solve(int t, int l, int r, LB G) {
  int lasttop = top;
  for (auto i : sgt[t]) {
    int u = i.u, v = i.v, w = i.w;
    int fu = find(u), fv = find(v);
    w ^= dis(u) ^ dis(v);
    if (fu == fv)
      G.add(w);
    else {
      merge(fu, fv, w);
    }
  }
  if (l == r)
    printf("%lld\n", G.Min1(dis(Q[l].first) ^ dis(Q[l].second)));
  else {
    int mid = (l + r) >> 1;
    solve(t << 1, l, mid, G);
    solve(t << 1 | 1, mid + 1, r, G);
  }
  while (lasttop < top) {
    dep[fa[st[top].x]] -= st[top].add;
    f[st[top].x] = 0;
    fa[st[top].x] = st[top].x;
    top--;
  }
}
int bg[MAXN], ed[MAXN];
int main() {
  freio();
  read(n, m);
  for (int i = 1; i <= n; i++) fa[i] = i;
  int c = m, tim = 1;
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    read(x, y, z);
    mp[make_pair(x, y)] = i, bg[i] = 1, ed[i] = -1, E[i] = {x, y, z};
  }
  read(q);
  while (q--) {
    int z, x, y;
    read(z, x, y);
    if (z == 1) {
      read(z);
      mp[make_pair(x, y)] = ++c, bg[c] = tim, ed[c] = -1;
      E[c] = {x, y, z};
    } else if (z == 2)
      ed[mp[make_pair(x, y)]] = tim - 1;
    else
      Q[tim].first = x, Q[tim].second = y, ++tim;
  }
  tim--;
  for (int i = 1; i <= c; i++)
    if (ed[i] == -1) ed[i] = tim;
  for (int i = 1; i <= c; i++)
    if (bg[i] <= ed[i]) insert(1, 1, tim, bg[i], ed[i], E[i]);
  solve(1, 1, tim, lb);
  return 0;
}
